home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / web / fweb / fweb-1.40 / demos / adj.web < prev    next >
Text File  |  1993-10-29  |  66KB  |  2,278 lines

  1. % $Id: adj.web,v 4.9 90/06/16 07:32:04 karney Exp $
  2.  
  3. % $Log:    adj.web,v $
  4. % Revision 4.9  90/06/16  07:32:04  karney
  5. % More documentation.
  6. % Revision 4.8  90/06/15  13:59:56  karney
  7. % Inserted more user documentation on how to compile and run the code.
  8. % Revision 4.7  90/05/11  17:37:26  karney
  9. % Cleaned up use of macros to provied generic UNIX version.  This should
  10. % probably be restructure to provide more orthogonality.
  11. % Revision 4.6  90/05/07  17:42:25  karney
  12. % Fix typo in readline addition.
  13. % Revision 4.5  90/05/07  12:24:15  karney
  14. % Use readline library to get terminal input on Sun
  15. % Revision 4.4  90/04/26  16:22:13  karney
  16. % Second attempt to get version number
  17. % Revision 4.3  90/04/26  16:19:54  karney
  18. % Include version number in title
  19. % Revision 4.2  90/04/19  14:46:35  karney
  20. % Minor cosmetic changes following John's suggestions
  21. % Revision 4.1  90/04/19  12:11:43  karney
  22. % Initial entry of Aug 22, 1989 version of code
  23.  
  24. \def\title{Adjoint function for a toroidal plasma; $ $Revision: 4.9 $ $}
  25.  
  26. % Change some of FWEB's formatting macros.
  27. \def\\#1{\leavevmode\hbox{\def\${{\sl \char`\$}}\def\%{\char`\%}%
  28.                           \it#1\/\kern.05em}} % Italic type for identifiers
  29. \def\@@#1{\leavevmode\hbox{\def\${\char`\$}\def\%{\char`\%}%
  30.                            \rm#1\kern.05em}} % Roman intrinsic functions
  31. \let\Csc=\rm       % Font for comments
  32.  
  33. % Some general math macros
  34. \def\abs#1{\left\vertbar#1\right\vertbar}    % Absolute values
  35. \def\frac#1#2{{#1\over#2}}
  36. \let\d=\partial
  37. \def\pd#1#2{\mathchoice{\d#1\over\d#2}{\d#1/\d#2}{\d#1/\d#2}{\d#1/\d#2}}
  38.  
  39. % Some shortcuts for this program
  40. \def\u{{\bf u}}\def\S{{\bf S}}
  41. \def\subb#1#2#3{_{#1[#2]#3}}
  42. \def\ja#1{\tilde\jmath_{#1}}
  43. \def\jn#1#2#3{\bar\jmath\subb{#1}{#2}{#3}}
  44. \def\qa#1{\tilde q_{#1}}
  45. \def\s{*}
  46. \def\lave#1{\overline{#1}}
  47.  
  48. @n
  49.  
  50. @* Introduction.  This program is supposed to calculate the Green's
  51. function for rf-driven current in an axisymmetric tokamak.  This is the
  52. solution to the Spitzer-H\"arm problem with the loop voltage $\Phi$ set to
  53. $TL/Q$.  The rf-driven current density is given by
  54. $$J_{\parallel 0}= \int d^3\u_0\, \lambda \S_0\cdot\nabla_0\chi,$$
  55. where $\S_0$ is the bounce-averaged rf-induced flux (at the midplane).
  56.  
  57. In this program, velocities are normalized to an arbitrary reference
  58. velocity $u_n$ (which is usually either $\sqrt{T/m}$ or $c$), times to
  59. $\tau_n=(\Gamma^{e/e}/u_n^3)^{-1}$, current densities to $qnu_n$, fluxes to
  60. $n/(\tau_n u_n^2)$, and $\chi$ to $qu_n\tau_n$.
  61.  
  62. (1) May 3, 1989:
  63. Initial version with only the first Legendre harmonic running for RF
  64. conference, May 1--3, 1989.
  65.  
  66. (2) May 29, 1989:
  67. Include an arbitrary number Legendre harmonics.
  68.  
  69. (3) May 31, 1989:
  70. Convert to using dynamic memory allocation.
  71.  
  72. (4) August 22, 1989:
  73. Allow choice on boundary conditions at $u_{\rm max}$.
  74.  
  75. @ This program is written to run on VAX/VMS systems, Sun Sparcstations
  76. (using double precision) and on Crays with cft77 (using single precision).
  77. This is controlled by four macros |VAX|, |SUN|, |CRAY|, |UNIX|.  It should be
  78. relatively straightforward to modify to program to run in other
  79. environments.  The major system dependent aspect of this code is the use of
  80. dynamic memory.  However this is easily turned off using the macros
  81. |STATIC|.  Then all memory is taken from a single statically allocated
  82. array of size |MEMSIZE|.
  83.  
  84. For the VAX, the prgram should be created with:
  85.  
  86. {\parskip=0pt\parindent=10em\tt
  87. ftangle -mVAX adj\par
  88. fortran/g\_float adj\par
  89. link adj\par}
  90.  
  91. For the Cray, use:
  92.  
  93. {\parskip=0pt\parindent=10em\tt
  94. ftangle -mCRAY -d  adj\par
  95. {\rm (send {\tt adj.f} to Cray)}\par
  96. cf77 -o adj adj.f\par}
  97.  
  98. (The {\tt -d} converts |do|/|end do| constructions into labeled |do|
  99. loops.)
  100.  
  101. For the Sun, use:
  102.  
  103. {\parskip=0pt\parindent=10em\tt
  104. ftangle -mSUN -=c=\#.web.c adj\par
  105. f77 -I/usr/gnu/include adj.f adj.web.c -o adj $\backslash$\par
  106. \hskip3em -L/usr/gnu/lib -lreadline -ltermcap\par}
  107.  
  108. If you need to use static memory, then specify {\tt -mSTATIC -m"MEMSIZE
  109. 100000"} to ftangle; this uses static memory of size 100000.
  110.  
  111. @ Input parameters.  When you run this program it asks you to input the
  112. following parameters: |t|, |c2|, |ze|, |zi|, |eps|, |nmax|, |umax|, |imax|,
  113. |kmax|, |dt|, |tmax|, |alpha|, |rho|, |lmax|.
  114.  
  115. |t| is the temperature in units of $m u_n^2$.  Thus if you want velocities
  116. normalized to $\sqrt{T/m}$, set $t = 1$.  Alternatively if normalization is
  117. to speed of light, set $t = T/(mc^2)$.
  118.  
  119. |c2| is the square of the speed of light (normalized to $u_n^2$).  If you
  120. want to run nonrelativistic cases, then set $t=1$ and ${\it c2} = 10^{20}$.
  121.  
  122. |ze| is the electron charge state.  This is usually 1, but you can get the
  123. Lorentz limit $Z_i\to\infty$ with $|ze|=0$ and $|zi|=1$.
  124.  
  125. |zi| is the ion charge state.
  126.  
  127. |eps| is the inverse aspect ratio $r/R$.  This is only used in the magnetic
  128. field routine |deltab|.  This routine is currently set up to define a
  129. circular cross-section tokamak.  $\epsilon=0$ corresponds to a uniform
  130. magnetic field (no trapped particles).
  131.  
  132. |nmax| is the number of grid points in the $u_0$ direction.
  133.  
  134. |umax| is the maximum value of $\abs{{\bf u}_0}$.  The $u_0$ grid is evenly
  135. spaced between $0$ and $u_{\rm max}$.
  136.  
  137. |imax| is the number of grid points in the $\theta_0$ direction.  The
  138. $\theta_0$ grid is evenly space between $0$ and $\theta_{\rm tr}$, the
  139. trapping angle.  $\chi({\bf u}_0)$ is odd about $\theta = \pi/2$ and is
  140. zero for $\theta_{\rm tr} < \theta < \pi - \theta_{\rm tr}$ in the trapped
  141. zone.
  142.  
  143. |kmax| is the number of integration points for field line integrals.  These
  144. are only done once at the beginning of a run, so |kmax| should be set quite
  145. large (e.g., 1000).
  146.  
  147. |dt| is the time step.  This needs to be chosen large enough to get to the
  148. steady state quickly but not so large that the iteration becomes unstable.
  149. A typical value is 1.
  150.  
  151. |tmax| is the number of time steps, typically 100--300.
  152.  
  153. |alpha| is a weighting factor in the time stepping algorithm.  $\alpha=0$
  154. gives an explicit algorithm.  $\alpha=0.5$ gives Crank-Nicholson iteration.
  155. $\alpha=0.55$ (i.e., a small amount of forward weighting) seems to be best.
  156.  
  157. |rho| governs the treatment of the boundary at $u=u_{\rm max}$.  For
  158. $\rho=1$, we have $\chi''(u_{\rm max})=0$, and for $\rho=0$, we have
  159. $\chi'(u_{\rm max})=0$.  The boundary has the least effect on the solution
  160. in the interior for $\rho=1$.
  161.  
  162. |lmax| is the maximum number of Legendre harmonics.  $|lmax|=0$ corresponds
  163. to collision off a Maxwellian.  For $\epsilon=0$, set $|lmax|=1$ (since
  164. $\chi$ consists of the first Legendre harmonic only).  Otherwise try
  165. $|lmax|=21$.
  166.  
  167. The program cycles through repeatedly asking for input until the end of the
  168. input file (for terminal input this is Control-Z on the VAX or Control-D on
  169. the Sun) or else nonpositive values are read in for |t| or |c2|.
  170.  
  171. @ Output.  This program outputs a small amount of data to the terminal plus
  172. a file of unformatted data.
  173.  
  174. The terminal output consists of an echo of the input parameters.  Every 10
  175. time steps, a line is written out consisting of |time|, |cond|, |abserr|,
  176. |relerr|.  |time| is the time step.  |cond| is the present estimate of the
  177. electrical conductivity (which this program calculates because $\chi$ is
  178. just the Spitzer-H\"arm function).  |abserr| and |relerr| are estimates of
  179. the absolute and relative errors in $\chi$ based on the residue.
  180.  
  181. The data written to the file consists of the input variables, the $u$ and
  182. $\theta_0$ arrays and a two-dimensional array for $\chi$.  See the section
  183. ``Write out results to disk.''  Note that $\chi$ and $f_m$ are defined at
  184. the mid-points of the cells i.e., at $u=|ua(n)|$, $\theta_0=|th0(i)|$ for
  185. $0\le n<n_{\rm max}$, $0\le i<i_{\rm max}$.
  186.  
  187. @ Files.  The program talks to three different files, which we call
  188. |input|, |output|, |adjout|.  |input| and |output| are normally terminal
  189. input and output.  |adjout| is the output file of unformatted data (see
  190. above).
  191.  
  192. On the VAX, the system supplies a {\tt .dat} file type to the |adjout| file
  193. (i.e., it is normally the {\tt adjout.dat} in the current directory).  You
  194. can redirect |input| and |output| from/to a file and rename the file
  195. |adjout| with VAX logical names.  For example:
  196.  
  197.  
  198. {\parskip=0pt\parindent=10em\tt
  199. define/user sys\$output adj2.in\par
  200. define/user sys\$input adj2.out\par
  201. define/user adjout adj2.dat\par
  202. r adj\par}
  203.  
  204. On the Sun, you can use normal file redirection for |input| and |output|.  You have to rename |adjout| explicity.  For example:
  205.  
  206. {\parskip=0pt\parindent=10em\tt
  207. adj <adj2.in >adj2.out\par
  208. mv adjout adj2.dat\par}
  209.  
  210. On the Cray, your can use command line arguments to specify file names.
  211. For example:
  212.  
  213. {\parskip=0pt\parindent=10em\tt
  214. adj input=adj2.in output=adj2.out adjout=adj2.dat\par}
  215.  
  216. @ References:
  217.  
  218. [1] B. J. Braams and C. F. F. Karney, {\it Conductivity of a relativistic
  219. plasma}, Phys.~Fluids {\bf 1B}, 1355--1368 (1989).
  220.  
  221. [2] C. F. F. Karney, N. J. Fisch, and A. H. Reiman,
  222. {\it Green's function for rf-driven current in a toroidal plasma},
  223. in {\it Radio-Frequency Power in Plasmas},
  224. Proc.\ Eighth Topical Conf. on Radio Frequency Plasma Heating,
  225. University of California, Irvine, CA,
  226. May 1--3, 1989,
  227. edited by R. McWilliams,
  228. AIP Conference Proceedings, No. 190
  229. (AIP, New York, 1989), pp.~430--433.
  230.  
  231. [3] C. F. F. Karney and N. J. Fisch, {\it Efficiency of Current Drive by
  232. Fast Waves}, Phys.~Fluids {\bf 28}, 116--126 (1985).
  233.  
  234. [4] C. F. F. Karney, {\it Fokker--Planck and Quasilinear Codes},
  235. Computer Physics Reports {\bf 4}, 183--244 (1986).
  236.  
  237. @ Macros for machine dependencies.
  238.  
  239. @#if defined(CRAY)
  240. @m CRAY 1
  241. @m SUN 0
  242. @m VAX 0
  243. @m UNIX 0
  244. @#elif defined(SUN)
  245. @m CRAY 0
  246. @m SUN 1
  247. @m VAX 0
  248. @m UNIX 0
  249. @#elif defined(VAX)
  250. @m CRAY 0
  251. @m SUN 0
  252. @m VAX 1
  253. @m UNIX 0
  254. @#else
  255. @m CRAY 0
  256. @m SUN 0
  257. @m VAX 0
  258. @m UNIX 1
  259. @#endif
  260.  
  261. @ Define precision.
  262.  
  263. @#if VAX || SUN || UNIX  /* Use double precision on the VAX and Sun*/
  264. @m real     double precision /* Default precision */
  265. @m areal    DBLE             /* Coerce to default precision */
  266. @m const(x) x##d0            /* Constant in default precision */
  267. @m epsilon  1.0d-16          /* Approximate round-off error */
  268. @m single   REAL             /* Coerce to single precision */
  269. @m memunit  8                /* Size of a real in bytes (the VAX's unit of
  270.                                  memory) */
  271. @#endif
  272.  
  273. @#if CRAY /* Use single precision on the Cray */
  274. @m real     REAL
  275. @m areal    REAL
  276. @m const(x) x##e0
  277. @m epsilon  1.0e-16
  278. @m single   REAL
  279. @m memunit  1                /* Size of a real in words (the Cray's unit of
  280.                                 memory) */
  281. @#endif
  282.  
  283. @ I/O units.  Also set things up to use the readline library if it's
  284. available (to permit editing and recall of input lines).
  285.  
  286. @m outunit  6
  287. @m diskunit 20
  288.  
  289. @#if !defined(READLINE)
  290. @#if SUN
  291. @m READLINE 1
  292. @#else
  293. @m READLINE 0
  294. @#endif
  295. @#endif
  296.  
  297. @#if READLINE
  298. @m LINELEN 80
  299. @m inunit   line(1:min(linelen,LINELEN))
  300. @#else
  301. @m inunit   5
  302. @#endif
  303.  
  304. @ Label definitions.
  305.  
  306. @m Start    #:0
  307. @m Exit     #:0
  308.  
  309. @ The Sun uses |implicit undefined(a-z)| instead of |implicit none|
  310.  
  311. @f implicit_none implicit
  312. @#if SUN
  313. @m implicit_none implicit undefined(a-z)
  314. @#else
  315. @m implicit_none implicit none
  316. @#endif
  317.  
  318.  
  319.  
  320. @ Abbreviated names for some identifiers.  CFT cannot handle identifiers
  321. longer than 8 characters.
  322.  
  323. @#if CRAY
  324. @m maxwellian    maxwel
  325. @m potential     pot
  326. @m isotropic     isotrop
  327. @m matrixinit    matinit
  328. @m legendrej     legj
  329. @m legendrejs    legjs
  330. @m legendrejn    legjn
  331. @#endif
  332.  
  333. @* The main program.
  334.  
  335.  
  336. @a
  337.       program adjoint
  338.  
  339.       implicit_none
  340.       integer nmax,imax,kmax,tmax,lmax,tskip
  341.       real t,c2,ze,zi,eps,umax,dt,alpha,rho
  342.       real cpu,cpu0
  343.       external operinit,second,runa
  344. @#if READLINE
  345.       character line*LINELEN
  346.       integer readline,linelen
  347.       external readline
  348. @#endif
  349.  
  350.       call operinit            /* Open files */
  351.  
  352. Start: continue
  353.  
  354.       write(outunit,*)
  355.      $     'Enter t,c2,ze,zi,eps,nmax,umax,imax,kmax,dt,tmax,alpha,rho,lmax'
  356. @#if READLINE
  357.       linelen=readline("> ",line)
  358.       if (linelen<=0) then
  359.          write(outunit,*)
  360.          goto Exit
  361.       end if
  362. @#endif
  363.       read(inunit,*,end=Exit) t,c2,ze,zi,eps,nmax,umax,imax,kmax,
  364.      $     dt,tmax,alpha,rho,lmax
  365.       if (t<=0 || c2<=0) goto Exit
  366.       write(outunit,*) t,c2,ze,zi,eps,nmax,umax,imax,kmax,
  367.      $     dt,tmax,alpha,rho,lmax
  368.       tskip=10
  369.  
  370.       call second(cpu0)
  371.  
  372.       call runa(t,c2,ze,zi,eps,nmax,umax,imax,kmax,dt,tmax,
  373.      $     alpha,rho,lmax,tskip)
  374.  
  375.       call second(cpu)
  376.  
  377.       write(outunit,'(1x,a,f10.2,a)') 'CPU time: ',cpu-cpu0,' secs'
  378.  
  379.       goto Start
  380.  
  381. Exit: continue
  382.  
  383.       stop
  384.       end
  385.  
  386.       @<Functions and subroutines@>
  387.  
  388. @#if SUN || UNIX
  389. @c
  390.       @<C functions@>
  391. @#endif
  392.  
  393. @ Open files for the CRAY.
  394.  
  395. @m STRING(s) #s   /* Macros get unit numbers into argument of |link|. */
  396. @m S(s)      STRING(s)
  397.  
  398. @<Functions...@>=
  399. @#if CRAY
  400.       subroutine operinit
  401.  
  402.       implicit_none
  403.       external link
  404.  
  405.       call link('input=terminal,unit'//S(inunit)//'=(input,open,text),'// @|
  406.      $     'output=terminal,unit'//S(outunit)//'=(output,create,text),'// @|
  407.      $     'print'//S(outunit)//','// @|
  408.      $     'unit'//S(diskunit)//'=(adjout,create,seq)//')
  409.  
  410.       return
  411.       end
  412. @#endif
  413.  
  414. @ Open files for the VAX.  Define a function to get the CPU time
  415.  
  416. @<Functions...@>=
  417. @#if VAX
  418.       subroutine operinit
  419.  
  420.       implicit_none
  421.       external lib$init_timer
  422.  
  423.       call lib$init_timer
  424.       open(unit=diskunit,file='adjout',form='unformatted',status='new')
  425.  
  426.       return
  427.       end
  428.  
  429.       subroutine second(cpu)
  430.  
  431.       implicit_none
  432.       integer cputime
  433.       real cpu
  434.       external lib$stat_timer
  435.  
  436.       call lib$stat_timer(2,cputime) /* |cputime| is in 10 ms increments */
  437.       cpu=const(0.01)*cputime /* convert to seconds */
  438.  
  439.       return
  440.       end
  441. @#endif
  442.  
  443. @ Open files for the SUN.  Define a function to get the CPU time
  444.  
  445. @<Functions...@>=
  446. @#if SUN || UNIX
  447.       subroutine operinit
  448.  
  449.       implicit_none
  450.       integer cputime,clock
  451.       external clock
  452.  
  453.       cputime=clock()
  454.       open(unit=diskunit,file='adjout',form='unformatted',status='unknown')
  455.  
  456.       return
  457.       end
  458.  
  459.       subroutine second(cpu)
  460.  
  461.       implicit_none
  462.       integer cputime,clock
  463.       real cpu
  464.  
  465.       cputime=clock()
  466.       cpu=const(0.000001)*cputime /* convert to seconds */
  467.  
  468.       return
  469.       end
  470. @#endif
  471.  
  472. @ A readline function for the Sun.  This reads in a line with editing and
  473. recall using the Gnu readline library.
  474.  
  475. @<C functions@>=
  476. @#if READLINE
  477. #include <stdio.h>
  478. #include <strings.h>
  479. #include <readline/readline.h>
  480.  
  481. /* Read a string with a prompt returning string in |result|.  String length
  482. is returned as function value. */
  483. long int readline_ (prompt, result, lprompt, lresult)
  484. char prompt[], result[];
  485. long int lprompt, lresult;
  486. {
  487.   char *cprompt, *cresult;
  488.   cprompt = (char *)malloc (lprompt+1);
  489.   strncpy (cprompt,prompt,lprompt);
  490.   cprompt[lprompt] = 0;
  491.  
  492.   /* Get a line from the user. */
  493.   cresult = readline (cprompt);
  494.   free (cprompt);
  495.  
  496.   /* If the line has any text in it, save it on the history. */
  497.   if (cresult && *cresult)
  498.     add_history (cresult);
  499.  
  500.   if (cresult == (char *)NULL) {
  501.     return (EOF);
  502.   } else {
  503.     strncpy (result, cresult, lresult);
  504.     lresult = strlen (cresult);
  505.     free (cresult);
  506.     return (lresult);
  507.   }
  508. }
  509. @#endif
  510.  
  511. @ Some C compatibility routines for the Sun.
  512.  
  513. @<C functions@>=
  514. @#if SUN || UNIX
  515. long clock_()            /* Interface to C clock routine */
  516. {
  517.   return(clock());
  518. }
  519. @#endif
  520.  
  521. @* Memory allocation.  All memory for arrays is allocated in |runa|.  When
  522. tangled for static memory allocation, the memory is taken from a single
  523. statically allocated array |memory| of size |MEMSIZE|.  For dynamic memory
  524. allocation, memory is obtained using |lib$get_vm| or |mzalloc|.  These
  525. return an address of a memory block.  This is associated with an array with
  526. a pointer statement (for the Cray) or by passing the address by value down
  527. to |runb|.  (See the definition of the macro |mem|.)
  528.  
  529. @#if !UNIX
  530. @#if defined(STATIC)
  531. @m STATIC 1        /* Allocate memory statically? */
  532. @#else
  533. @m STATIC 0
  534. @#endif
  535. @#else
  536. @m STATIC 1
  537. @#endif
  538.  
  539. @#if !defined(MEMSIZE)
  540. @m MEMSIZE 4000
  541. @#endif
  542.  
  543. @ Utility macros for memory allocation.  For each array used in |runb|, a
  544. index is defined by prepending a |p| to the name of the array.  This index
  545. is then defined using |alloc|.  Arrays which are local to a single
  546. subroutine are allocated from a single array |work|.  |workalloc| figures
  547. out the size of this array.
  548.  
  549. @m ptr(x)        p##x  /* A pointer into |memory| formed by prepending |p| */
  550. @m alloc(x,y)    ptr(x)=memsize; memsize=memsize+y;
  551. @m workalloc(y)  worksize=max(worksize,y)
  552.  
  553. @#if STATIC
  554. @m mem(x)        memory(ptr(x))
  555. @#else
  556. @#if VAX
  557. @m mem(x)        %val(baseaddr+memunit*ptr(x))
  558. @#endif
  559. @#if CRAY || SUN
  560. @m mem(x)        memory(ptr(x))
  561. @#endif
  562. @#endif
  563.  
  564. @ Since we deal only in harmonic numbers $l$ equal to 0, 1, 3, 5, etc., we
  565. also define macros to map between these and an index |la| equation to 0, 1,
  566. 2, 3, etc.  We also need macros to index into two non-rectangular arrays
  567. |garr| and |harr|.
  568.  
  569. @m laf(l)   (l+1)/2      /* Map |l| onto collapsed index |la| */
  570. @m lf(la)   max(2*la-1,0)  /* Map |la| onto expanded index |l| */
  571.  
  572. @m gind(la,la1)     ((((la+3)-1)*(la+3))/2 + (la1+1))
  573. @m gv(la,la1)       garr(gind(la,la1))
  574. @m hind(la,la1,la2) (((la-1)*la*(2*la-1))/6 + (la1-1)*la + la2)
  575. @m hv(la,la1,la2)   harr(hind(la,la1,la2))
  576.  
  577. @ Allocate the necessary memory and call |runb| to do the actual
  578. computation.
  579.  
  580. @f @<Declare memory allocation stuff@> integer
  581. @f @<Index declarations@> integer
  582. @f pointer integer
  583.  
  584. @<Functions...@>=
  585.       subroutine runa(t,c2,ze,zi,eps,nmax,umax,imax,kmax,dt,tmax,
  586.      $    alpha,rho,lmax,tskip)
  587.  
  588.       implicit_none
  589.       integer nmax,imax,kmax,tmax,lmax,tskip
  590.       real t,c2,ze,zi,eps,umax,dt,alpha,rho
  591.  
  592.       integer nmax1,imax1,lmaxa,lmaxa1
  593.       @<Declare memory allocation stuff@>
  594.       external runb
  595.  
  596.  /* |nmax1| and |imax1| are the allocated dimensions for two-dimensional
  597.  arrays.  These might differ from |nmax| and |imax| on the Crays, where even
  598.  strides are inefficiently handled. */
  599.       nmax1=nmax
  600.       imax1=imax
  601. @#if CRAY   /* To avoid memory conflicts on the Crays */
  602.       if (mod(nmax1,2)==1) nmax1=nmax1+1   /* Make even for accessing
  603.                |ijy(0:nmaxa1,0:6,0:1)| by row in |potential| */
  604.       if (mod(imax1,2)==0) imax1=imax1+1   /* Make odd for accessing
  605.                |chi(0:imax1-1,0:nmax-1)| by row in |decomp| */
  606. @#endif
  607.  
  608.  /* |lmaxa1| is the allocated dimension for the |la| index.  This is
  609.  usually |lmaxa| but must be at least $1$ to ensure that dimension
  610.  specifications such as |1:lmaxa1| are legal.  Also $H_{1,1,1}$ is needed
  611.  even when |lmaxa=0|. */
  612.  
  613.       if (mod(lmax,2)==0) lmax=lmax-1  /* Round |lmax| down to an odd number */
  614.       lmaxa=laf(lmax)
  615.       lmaxa1=lmaxa
  616.       if (lmaxa1==0) lmaxa1=1        /* But |lmaxa1| needs to be at least 1 */
  617.  
  618.       memsize=0
  619.       worksize=0
  620.       @<Index specifications@>  /* Define all the array pointers and
  621.                                    figure |worksize| */
  622.       alloc(work,worksize)
  623.  
  624.       @<Allocate memory@>
  625.  
  626.       call runb(t,c2,ze,zi,eps,nmax,umax,imax,kmax,dt,tmax,
  627.      $     alpha,rho,lmax,tskip,
  628.      $     nmax1,imax1,lmaxa,lmaxa1,worksize,
  629.      $     mem(ua),mem(ug),mem(th0a),mem(th0g),mem(csth0a),mem(chi),
  630.      $     mem(legjy),mem(chil),mem(legp),mem(duug),mem(fu),mem(dtt),
  631.      $     mem(fm),mem(psid),mem(lam1a),mem(lam2g),mem(harr),mem(uinv),
  632.      $     mem(th0inv),mem(resid),mem(resida),mem(work))
  633.  
  634.       @<Deallocate memory@>
  635.  
  636.       return
  637.       end
  638.  
  639. @
  640. @<Declare memory allocation stuff@>=
  641.       integer memsize,worksize,ptr(work)
  642.       @<Index declarations@>
  643. @#if STATIC
  644.       real memory
  645.       dimension memory(0:MEMSIZE-1)
  646. @#else
  647. @#if VAX
  648.       integer baseaddr,status,lib$get_vm,lib$free_vm
  649.       external lib$get_vm,lib$free_vm
  650. @#endif
  651. @#if CRAY
  652.       real memory
  653.       dimension memory(0:*)
  654.       pointer (baseaddr,memory)
  655.       integer status,mzalloc,mzdalloc
  656.       external mzalloc,mzdalloc
  657. @#endif
  658. @#if SUN
  659.       real memory
  660.       dimension memory(0:*)
  661.       pointer (baseaddr,memory)
  662.       integer status,malloc
  663.       external malloc,free
  664. @#endif
  665. @#endif
  666.  
  667. @ Allocate memory required using the appropriate system calls.
  668.  
  669. @#if !STATIC
  670. @#if VAX
  671. @m memalloc(size,addr)   status=lib$get_vm(size,addr)
  672. @m memdealloc(size,addr) status=lib$free_vm(size,addr)
  673. @m bad(s)                mod(s,2)==0
  674. @#endif
  675. @#if CRAY
  676. @m memalloc(size,addr)   status=mzalloc(addr,size)
  677. @m memdealloc(size,addr) status=mzdalloc(addr,size)
  678. @m bad(s)                s!=0
  679. @#endif
  680. @#if SUN
  681. @m memalloc(size,addr)   addr=malloc(size); status=addr
  682. @m memdealloc(size,addr) call free(size)
  683. @m bad(s)                s==0
  684. @#endif
  685. @#endif
  686.  
  687. @<Allocate memory@>=
  688. @#if STATIC
  689.       if (memsize>MEMSIZE) then
  690.          write(outunit,*) 'Memory needed/allocated: ', memsize, '/', MEMSIZE
  691.          return
  692.       end if
  693. @#else
  694.       memalloc(memunit*memsize,baseaddr)
  695.       if (bad(status)) then
  696.          write(outunit,*) 'Couldn''t allocate memory: ',memsize
  697.          return
  698.       end if
  699. @#endif
  700.  
  701. @
  702. @<Deallocate memory@>=
  703. @#if !STATIC
  704.       memdealloc(memunit*memsize,baseaddr)
  705. @#endif
  706.  
  707. @* Do a case.
  708.  
  709. @f @<Global declarations@> integer
  710.  
  711. @<Functions...@>=
  712.       subroutine runb(t,c2,ze,zi,eps,nmax,umax,imax,kmax,dt,tmax,
  713.      $    alpha,rho,lmax,tskip,
  714.      $    nmax1,imax1,lmaxa,lmaxa1,worksize,
  715.      $    ua,ug,th0a,th0g,csth0a,chi,legjy,chil,legp,duug,fu,dtt,
  716.      $    fm,psid,lam1a,lam2g,harr,uinv,th0inv,resid,resida,work)
  717.  
  718.       implicit_none
  719.  
  720.       integer worksize
  721.       real work
  722.       dimension work(0:worksize-1)
  723.  
  724.       @<Global declarations@>
  725.  
  726.       @<Initialization@>
  727.  
  728.       do time=0,tmax
  729.          @<Make a step@>
  730.       end do
  731.  
  732.       @<Write out results@>
  733.  
  734.       return
  735.       end
  736.  
  737. @* The velocity space meshes.
  738.  
  739. @<Glob...@>=
  740.       integer nmax,imax,nmax1,imax1,n,i
  741.       real du,umax,ua,ug,dth0,th0max,th0a,th0g,csth0a,chi @/
  742.  /* The velocity mesh */
  743.       dimension ua(0:nmax-1),ug(0:nmax),th0a(0:imax-1),th0g(0:imax),
  744.      $    csth0a(0:imax-1),chi(0:imax1-1,0:nmax-1)
  745.       real pi
  746.  
  747. @ Define the indices for velocity space meshes in main memory of |runa|.
  748. @<Index decl...@>=
  749.       integer ptr(ua),ptr(ug),ptr(th0a),ptr(th0g),ptr(csth0a),ptr(chi)
  750.  
  751. @ Allocate the space needed for these arrays.
  752. @<Index spec...@>=
  753.       alloc(ua,nmax)
  754.       alloc(ug,nmax+1)
  755.       alloc(th0a,imax)
  756.       alloc(th0g,imax+1)
  757.       alloc(csth0a,imax)
  758.       alloc(chi,imax1*nmax)
  759.  
  760. @ Initialize velocity meshes, $\chi$, etc.
  761.  
  762. @<Init...@>=
  763.       du=umax/nmax
  764.       do n=0,nmax-1
  765.          ua(n)=(n+const(0.5))*du
  766.          ug(n)=n*du
  767.       end do
  768.       ug(nmax)=umax
  769.  
  770.       pi=4*atan(const(1.0))
  771.       th0max=atan2(const(1.0),sqrt(deltab(pi,eps))) /* $\sin^{-1}(1/\sqrt b)$*/
  772.       dth0=th0max/imax
  773.       do i=0,imax-1
  774.          th0a(i)=(i+const(0.5))*dth0
  775.          csth0a(i)=cos(th0a(i))
  776.          th0g(i)=i*dth0
  777.       end do
  778.       th0g(imax)=th0max
  779.  
  780.       do n=0,nmax-1
  781.          do i=0,imax-1
  782.             chi(i,n)=0
  783.          end do
  784.       end do
  785.  
  786. @* Potentials.  The following routines calculate the potentials and their
  787. derivatives.  First define arrays to hold Legendre functions evaluated on
  788. the velocity mesh.
  789.  
  790. @m jl(n,a,la)  legjy(n,a,0,la)
  791. @m yl(n,a,la)  legjy(n,a,1,la)
  792. @m djl(n,a,la) legjy(n,a,2,la)
  793. @m dyl(n,a,la) legjy(n,a,3,la)
  794.  
  795. @<Glob...@>=
  796.       real c,c2
  797.       real legjy            /* Arrays holding Legendre functions */
  798.       integer lmax,lmaxa,lmaxa1
  799.       dimension legjy(0:nmax1-1,0:6,0:3,0:lmaxa1)
  800.       external initjy
  801.  
  802. @
  803. @<Index decl...@>=
  804.       integer ptr(legjy)
  805.  
  806. @
  807. @<Index spec...@>=
  808.       alloc(legjy,nmax1*7*4*(lmaxa1+1))
  809.  
  810. @ Fill the arrays.
  811. @<Init...@>=
  812.       c=sqrt(c2)
  813.       lmaxa=laf(lmax)
  814.       call initjy(ua,c,nmax,nmax1,lmaxa,lmaxa1,legjy,
  815.      $     work(0),work(2*(lf(lmaxa)+2+1)*7),lf(lmaxa)+2)
  816.  
  817. @ Define |initjy|.
  818. @<Functions...@>=
  819.       subroutine initjy(ua,c,nmax,nmax1,lmaxa,lmaxa1,
  820.      $    legjy,jarray,djarray,lmax1)
  821.  
  822.       implicit_none
  823.       integer nmax,nmax1,lmaxa,lmaxa1,n,mult,la,l,a,lmax1
  824.       real ua,legjy,c,jarray,djarray
  825.       dimension ua(0:nmax-1),legjy(0:nmax1-1,0:6,0:3,0:lmaxa1)
  826.       dimension jarray(-lmax1-1:lmax1,0:6),djarray(-lmax1-1:lmax1,0:6)
  827.       external legendrejn
  828.  
  829.       do n=0,nmax-1
  830.          call legendrejn(ua(n),c,lf(lmaxa),jarray,djarray,lmax1)
  831.          do la=0,lmaxa
  832.             l=max(lf(la),0)
  833.             mult=(-1)^(l+1)
  834.             do a=0,6
  835.                jl(n,a,la)=jarray(l,a)
  836.                yl(n,a,la)=mult*jarray(-l-1,a)
  837.                djl(n,a,la)=djarray(l,a)
  838.                dyl(n,a,la)=mult*djarray(-l-1,a)
  839.             end do
  840.          end do
  841.       end do
  842.  
  843.       return
  844.       end
  845.  
  846. @ Figure the workspace for |initjy| (|jarray| and |djarray|).
  847. @<Index spec...@>=
  848.       workalloc(2*(lf(lmaxa)+2+1)*7 * 2)
  849.  
  850. @ Calculate the potentials and their derivates for the $l$th Legendre
  851. harmonic.
  852.  
  853. These are some definitions so we don't have to pass a whole slew of arrays
  854. around to subroutines.
  855.  
  856. @m j(n,a)      legjy(n,a,0)     /* Short-hand expressions for $j$, $y$, their
  857.  derivatives and integrals. */
  858. @m y(n,a)      legjy(n,a,1)
  859. @m dj(n,a)     legjy(n,a,2)
  860. @m dy(n,a)     legjy(n,a,3)
  861. @m ij(n,a)     ijy(n,a,0)
  862. @m iy(n,a)     ijy(n,a,1)
  863.  
  864. @m psi(n,a)    psid(n,a,0)
  865. @m dpsi(n,a)   psid(n,a,1)
  866.  
  867.  
  868. @ Subroutine to calculate the potentials.  This is a straight
  869. implementation of equations (31) and (22).
  870.  
  871. @<Functions...@>=
  872.       subroutine potential(ua,du,c,fm,chil,nmax,nmax1,legjy,psid,fla,ijy)
  873.  
  874.       implicit_none
  875.       integer p0,p02,p022,p1,p11
  876.       parameter (p0=0, p02=1, p022=2, p1=3, p11=4)
  877.       integer j0,j1,j2,j02,j11,j22,j022
  878.       parameter (j0=0, j1=1, j2=2, j02=3, j11=4, j22=5, j022=6)
  879.  
  880.       integer nmax,nmax1,n,a
  881.       real ua,du,c,fm,chil,legjy
  882.       dimension ua(0:nmax-1),fm(0:nmax-1),chil(0:nmax-1),
  883.      $     legjy(0:nmax1-1,0:6,0:3)
  884.       real psid
  885.       dimension psid(0:nmax1-1,0:4,0:1)
  886.       real fla,ijy
  887.       dimension fla(0:nmax-1),ijy(0:nmax1,0:6,0:1)
  888.  
  889.       @<Define various indefinite integrals@>
  890.  
  891.       do n=0,nmax-1
  892.          psi(n,p0) = y(n,j0)*ij(n,j0) + iy(n,j0)*j(n,j0)
  893.          psi(n,p02) = y(n,j0)*ij(n,j02) + y(n,j02)*ij(n,j2) +
  894.      $        iy(n,j0)*j(n,j02) + iy(n,j02)*j(n,j2)
  895.          psi(n,p022) = y(n,j0)*ij(n,j022) + y(n,j02)*ij(n,j22) +
  896.      $        y(n,j022)*ij(n,j2) + @|
  897.      $        iy(n,j0)*j(n,j022) + iy(n,j02)*j(n,j22) + iy(n,j022)*j(n,j2)
  898.          psi(n,p1) = y(n,j1)*ij(n,j1) + iy(n,j1)*j(n,j1)
  899.          psi(n,p11) = y(n,j1)*ij(n,j11) + y(n,j11)*ij(n,j1) +
  900.      $        iy(n,j1)*j(n,j11) + iy(n,j11)*j(n,j1)
  901.  
  902.          dpsi(n,p0) = dy(n,j0)*ij(n,j0) + iy(n,j0)*dj(n,j0)
  903.          dpsi(n,p02) = dy(n,j0)*ij(n,j02) + dy(n,j02)*ij(n,j2) +
  904.      $        iy(n,j0)*dj(n,j02) + iy(n,j02)*dj(n,j2)
  905.          dpsi(n,p022) = dy(n,j0)*ij(n,j022) + dy(n,j02)*ij(n,j22) +
  906.      $        dy(n,j022)*ij(n,j2) + @|
  907.      $        iy(n,j0)*dj(n,j022) + iy(n,j02)*dj(n,j22) + iy(n,j022)*dj(n,j2)
  908.          dpsi(n,p1) = dy(n,j1)*ij(n,j1) + iy(n,j1)*dj(n,j1)
  909.          dpsi(n,p11) = dy(n,j1)*ij(n,j11) + dy(n,j11)*ij(n,j1) +
  910.      $        iy(n,j1)*dj(n,j11) + iy(n,j11)*dj(n,j1)
  911.       end do
  912.  
  913.       return
  914.       end
  915.  
  916. @ Workspace for |potential| (|fla| and |ijy|).
  917. @<Index spec...@>=
  918.       workalloc(nmax + (nmax1+1)*7*2)
  919.  
  920. @ Define various indefinite integrals needed in the definition of the
  921. potentials.  First do the integration to cell edges and then interpolate to
  922. the cell centers.
  923.  
  924. @<Define various indefinite integrals@>=
  925.       do n=0,nmax-1
  926.          fla(n)=fm(n)*chil(n)*ua(n)^2/sqrt(1+(ua(n)/c)^2)*du/2
  927.       end do
  928.  
  929.       do a=0,6
  930.          do n=0,nmax-1                /* Define the integrand */
  931.             ij(n+1,a)=fla(n)*j(n,a)
  932.             iy(n,a)=fla(n)*y(n,a)
  933.          end do
  934.          ij(0,a)=0              /* Define the boundary condtions */
  935.          iy(nmax,a)=0
  936.       end do
  937.  
  938.       do n=1,nmax          /* Integrate to cell edges */
  939.          do a=0,6
  940.             ij(n,a)=ij(n-1,a)+ij(n,a)
  941.          end do
  942.       end do
  943.       do n=nmax-1,0,-1
  944.          do a=0,6
  945.             iy(n,a)=iy(n+1,a)+iy(n,a)
  946.          end do
  947.       end do
  948.  
  949.       do a=0,6
  950.          do n=0,nmax-1
  951.             ij(n,a)=ij(n,a)+ij(n+1,a)
  952.             iy(n,a)=iy(n,a)+iy(n+1,a)
  953.          end do
  954.       end do
  955.  
  956. @* Legendre harmonic decomposition.  Define arrays for Legendre harmonics
  957. and decompostion of $\chi$.
  958.  
  959. @<Glob...@>=
  960.       real chil,legp      /* Legendre decomposition of $\chi$ */
  961.       dimension chil(0:nmax1-1,1:lmaxa1),legp(0:imax1-1,1:lmaxa1)
  962.       external initp
  963.  
  964. @
  965. @<Index decl...@>=
  966.       integer ptr(chil),ptr(legp)
  967.  
  968. @
  969. @<Index spec...@>=
  970.       alloc(chil,nmax1*lmaxa1)
  971.       alloc(legp,imax1*lmaxa1)
  972.  
  973. @ Initialize |legp|.
  974.  
  975. @<Init...@>=
  976.       call initp(csth0a,imax,imax1,lmaxa,lmaxa1,legp,work)
  977.  
  978. @ Define |initp|.  Use the recursion formula for Legendre harmonics
  979. $$ (l+1) P_{l+1}(\mu) = (2l+1)\mu P_l(\mu) -  l P_{l-1}(\mu). $$
  980.  
  981. @<Functions...@>=
  982.       subroutine initp(x,imax,imax1,lmaxa,lmaxa1,legp,leg0)
  983.  
  984.       implicit_none
  985.       integer imax,imax1,lmaxa,lmaxa1,i,l,la
  986.       real x,legp
  987.       dimension x(0:imax-1),legp(0:imax1-1,1:lmaxa1)
  988.       real leg0
  989.       dimension leg0(0:imax-1)
  990.  
  991.       if (lmaxa<1) return    /* Nothing to do */
  992.  
  993.       la=1
  994.       do i=0,imax-1
  995.          leg0(i)=1
  996.          legp(i,la)=x(i)
  997.       end do
  998.  
  999.       do la=2,lmaxa
  1000.          l=lf(la)
  1001.          do i=0,imax-1
  1002.             leg0(i)=((2*l-3)*x(i)*legp(i,la-1)-(l-2)*leg0(i))/(l-1)
  1003.                         /* $P_{l-1}$ */
  1004.             legp(i,la)=((2*l-1)*x(i)*leg0(i)-(l-1)*legp(i,la-1))/l
  1005.                         /* $P_{l}$ */
  1006.          end do
  1007.       end do
  1008.  
  1009.       return
  1010.       end
  1011.  
  1012. @ Workspace for |initp| (|leg0|).
  1013. @<Index spec...@>=
  1014.       workalloc(imax)
  1015.  
  1016. @ Decompose $\chi$ into Legendre components.  We have
  1017. $$
  1018. \chi_l(u)=\frac{2l+1}{2}\int_0^{\pi} \chi(u,\theta_0) P_l(\cos\theta_0) 
  1019. \sin\theta_0\, d\theta_0.
  1020. $$
  1021. Since $\chi$ is odd in $\theta_0$ and it vanishes for the trapped
  1022. population this becomes
  1023. $$
  1024. \chi_l(u)=(2l+1)\int_0^{\theta_{0,\rm max}} \chi(u,\theta_0)  P_l(\cos\theta_0)
  1025. \sin\theta_0\, d\theta_0.
  1026. $$
  1027.  
  1028.  
  1029. @<Functions...@>=
  1030.       subroutine decomp(chi,nmax,nmax1,imax,imax1,lmaxa,lmaxa1,
  1031.      $    th0a,dth0,legp,chil)
  1032.  
  1033.       implicit_none
  1034.       integer nmax,nmax1,imax,imax1,lmaxa,lmaxa1,la,l,n,i
  1035.       real chi,th0a,dth0,legp,chil,sn
  1036.       dimension chi(0:imax1-1,0:nmax-1),th0a(0:imax-1),
  1037.      $     legp(0:imax1-1,1:lmaxa1),chil(0:nmax1-1,1:lmaxa1)
  1038.  
  1039.       do la=1,lmaxa
  1040.          l=lf(la)
  1041.  
  1042.          do n=0,nmax-1
  1043.             chil(n,la)=0
  1044.          end do
  1045.  
  1046.          do i=0,imax-1
  1047.             sn=sin(th0a(i))*legp(i,la)
  1048.             do n=0,nmax-1
  1049.                chil(n,la)=chil(n,la)+chi(i,n)*sn
  1050.             end do
  1051.          end do
  1052.  
  1053.          do n=0,nmax-1
  1054.             chil(n,la)=(2*l+1)*dth0*chil(n,la)
  1055.          end do
  1056.  
  1057.       end do
  1058.  
  1059.       return
  1060.       end
  1061.  
  1062. @* Coefficients for isotropic collision operator.  I.e., collisions off a
  1063. Maxwellian background.
  1064.  
  1065. @<Glob...@>=
  1066.       real t,ze,zi              /* Plasma parameters */
  1067.  
  1068.       real duug,fu,dtt
  1069.       dimension duug(0:nmax),fu(0:nmax-1),dtt(0:nmax-1)
  1070.  
  1071.       real fm      /* Maxwellian  */
  1072.       dimension fm(0:nmax-1)
  1073.  
  1074.       real psid         /* Arrays for potentials and their derivatives */
  1075.       dimension psid(0:nmax1-1,0:4,0:1)
  1076.  
  1077.       external maxwellian,isotropic
  1078.  
  1079. @
  1080. @<Index decl...@>=
  1081.       integer ptr(duug),ptr(fu),ptr(dtt),ptr(fm),ptr(psid)
  1082.  
  1083. @
  1084. @<Index spec...@>=
  1085.       alloc(duug,nmax+1)
  1086.       alloc(fu,nmax)
  1087.       alloc(dtt,nmax)
  1088.       alloc(fm,nmax)
  1089.       alloc(psid,nmax1*5*2)
  1090.  
  1091. @ Initialize isotropic terms.
  1092.  
  1093. @<Init...@>=
  1094.       call maxwellian(ua,du,c,nmax,fm,t)
  1095.  
  1096.       do n=0,nmax-1
  1097.          chil(n,1)=1
  1098.       end do
  1099.  
  1100.       call isotropic(ua,du,c,fm,chil(0,1),nmax,nmax1,legjy(0,0,0,0),psid,
  1101.      $     ze,zi,duug,fu,dtt,work)
  1102.  
  1103. @ This function calculates $D_{uu}$, $D_{\theta\theta}$ and $F_u$ from the
  1104. potentials.  This is a transcription of equations (33).
  1105.  
  1106. @<Functions...@>=
  1107.       subroutine isotropic(ua,du,c,fm,chil,nmax,nmax1,legjy,psid,
  1108.      $    ze,zi,duug,fu,dtt,work)
  1109.  
  1110.       implicit_none
  1111.       integer p0,p02,p022,p1,p11
  1112.       parameter (p0=0, p02=1, p022=2, p1=3, p11=4)
  1113.  
  1114.       integer nmax,nmax1,n
  1115.       real ua,c,psid,duug,fu,dtt,pi,g,u,ze,zi,du,fm,chil,legjy
  1116.       dimension ua(0:nmax-1),fm(0:nmax-1),chil(0:nmax-1),
  1117.      $     legjy(0:nmax1-1,0:6,0:3),psid(0:nmax1-1,0:4,0:1),
  1118.      $     duug(0:nmax),fu(0:nmax-1),dtt(0:nmax-1)
  1119.       real work
  1120.       dimension work(0:nmax+(nmax1+1)*7*2-1)
  1121.       external potential
  1122.  
  1123.       call potential(ua,du,c,fm,chil,nmax,nmax1,legjy,psid,work(0),work(nmax))
  1124.  
  1125.       pi=4*atan(const(1.0))
  1126.       do n=0,nmax-1
  1127.          u=ua(n)
  1128.          g=sqrt(1+(u/c)^2)
  1129.          duug(n)=ze * 4*pi*g/u*(2*g^2*dpsi(n,p02)-u*psi(n,p0)- @|
  1130.      $        8*g^2/c^2*dpsi(n,p022)+8*u/c^4*psi(n,p022))
  1131.          dtt(n)=ze * 4*pi/(g*u)*(-g^2*dpsi(n,p02)-u/c^2*psi(n,p02)+ @|
  1132.      $        4*g^2/c^2*dpsi(n,p022)-4*u/c^4*psi(n,p022))
  1133.      $        + zi * g/(2*u)
  1134.          fu(n)=ze * 4*pi*g*(-dpsi(n,p1)+2/c^2*dpsi(n,p11))
  1135.       end do
  1136.  
  1137.  /* Interpolate |duug| to cell edges.  Assume a constant first derivative at
  1138.  |umax| and a constant value at $u=0$. */
  1139.       duug(nmax)=(3*duug(nmax-1)-duug(nmax-2))/2
  1140.       do n=nmax-1,1,-1
  1141.          duug(n)=(duug(n)+duug(n-1))/2
  1142.       end do
  1143.       duug(0)=duug(0)
  1144.  
  1145.       return
  1146.       end
  1147.  
  1148.  
  1149. @ Define a Maxwellian distribution
  1150. $$
  1151. f_m(u) \propto \exp\biggl(-\frac{mc^2\gamma}{T}\biggr).
  1152. $$
  1153.  
  1154. @<Functions...@>=
  1155.       subroutine maxwellian(ua,du,c,nmax,fm,t)
  1156.  
  1157.       implicit_none
  1158.       integer nmax,n
  1159.       real ua,du,c,fm,t,sum,pi
  1160.       dimension ua(0:nmax-1),fm(0:nmax-1)
  1161.  
  1162.       sum=0
  1163.       do n=0,nmax-1
  1164.          fm(n)=exp(-ua(n)^2/(sqrt(1+(ua(n)/c)^2)+1)/t)
  1165.          sum=sum+ua(n)^2*fm(n)
  1166.       end do
  1167.       pi=4*atan(const(1.0))
  1168.       sum=4*pi*du*sum
  1169.       do n=0,nmax-1
  1170.          fm(n)=fm(n)/sum        /* Normalize to unit density */
  1171.       end do
  1172.  
  1173.       return
  1174.       end
  1175.  
  1176. @* Reaction terms.  Calculate the term
  1177. $$
  1178. I(\chi_l(u))=
  1179. \frac{C^{e/e}(f_{m}(u),f_{m}(u)\chi_{l}(u)P_l(\cos\theta))}
  1180. {f_{m}(u)P_l(\cos\theta)},
  1181. $$
  1182. using equation (37).  In fact we use a generalization of this equation for
  1183. arbitrary $l$.  This term is added to the |reactl|.
  1184.  
  1185. @<Functions...@>=
  1186.       subroutine reaction(ua,du,c,fm,t,chil,nmax,nmax1,legjy,psid,ze,reactl,l,
  1187.      $    work)
  1188.  
  1189.       implicit_none
  1190.       integer p0,p02,p022,p1,p11
  1191.       parameter (p0=0, p02=1, p022=2, p1=3, p11=4)
  1192.  
  1193.       integer nmax,nmax1,n,l
  1194.       real ua,du,c,legjy,psid,ze,reactl,fm,chil,t,pi,u,g
  1195.       dimension ua(0:nmax-1),legjy(0:nmax1-1,0:6,0:3),psid(0:nmax1-1,0:4,0:1),
  1196.      $     reactl(0:nmax-1),fm(0:nmax-1),chil(0:nmax-1)
  1197.       real work
  1198.       dimension work(0:nmax+(nmax1+1)*7*2-1)
  1199.       external potential
  1200.  
  1201.       call potential(ua,du,c,fm,chil,nmax,nmax1,legjy,psid,work(0),work(nmax))
  1202.  
  1203.       pi=4*atan(const(1.0))
  1204.       do n=0,nmax-1
  1205.          u=ua(n)
  1206.          g=sqrt(1+(u/c)^2)
  1207.          reactl(n)=reactl(n)+ze*4*pi*(
  1208.      $        fm(n)*chil(n)/g- @|
  1209.      $        u/t*dpsi(n,p1)-2/(c^2*g)*psi(n,p1)+2*u/(c^2*t)*dpsi(n,p11)+ @|
  1210.      $        u/t*dpsi(n,p0)-(u^2/(g*t^2)-1/t)*psi(n,p0)+ @|
  1211.      $        (2*g*u/t^2-2*u/(c^2*t))*dpsi(n,p02)-
  1212.      $        (l*(l+1)/(g*t^2)-2/(c^2*t))*psi(n,p02)- @|
  1213.      $        8*g*u/(c^2*t^2)*dpsi(n,p022)+
  1214.      $        4*((l+2)*(l-1)/g+2*g)/(c^2*t^2)*psi(n,p022)
  1215.      $        )
  1216.       end do
  1217.  
  1218.       return
  1219.       end
  1220.  
  1221. @ Sum up reaction terms
  1222. $$ \frac1{\lambda_1}
  1223.   \sum_l^{l_{\rm max}}\sum_{l',l''\ \rm odd}^l
  1224.   H_{l,l',l''} P_{l',0} I_l(\chi_{l'',0}).
  1225. $$
  1226. We can rewrite this as
  1227. $$ \frac1{\lambda_1}
  1228.   \sum_{l'=1}^{l_{\rm max}} P_{l',0}
  1229.     \sum_{l=l'}^{l_{\rm max}}
  1230.       I_l\biggl( \sum_{l''=1}^l H_{l,l',l''} \chi_{l'',0} \biggr).
  1231. $$
  1232.  
  1233. @<Functions...@>=
  1234.       subroutine reactall(ua,du,c,fm,t,chil,nmax,nmax1,imax,imax1,lam1a,
  1235.      $    legjy,psid,legp,harr,ze,lmaxa,lmaxa1,react,reactl,chila,work)
  1236.  
  1237.       implicit_none
  1238.       integer nmax,nmax1,imax,imax1,lmaxa,lmaxa1
  1239.       real ua,du,c,fm,t,chil,lam1a,legjy,psid,legp,harr,ze,react
  1240.       dimension ua(0:nmax-1),fm(0:nmax-1),chil(0:nmax1-1,1:lmaxa1),
  1241.      $     lam1a(0:imax-1),legjy(0:nmax1-1,0:6,0:3,1:lmaxa1),
  1242.      $     psid(0:nmax1-1,0:4,0:1),legp(0:imax1-1,1:lmaxa1),
  1243.      $     hv(lmaxa1,lmaxa1,lmaxa1),react(0:imax1-1,0:nmax-1)
  1244.       integer la,la1,la2,n,i
  1245.       real reactl,chila,work
  1246.       dimension reactl(0:nmax-1),chila(0:nmax-1),work(0:nmax+(nmax1+1)*7*2-1)
  1247.       external reaction
  1248.  
  1249.       do n=0,nmax-1
  1250.          do i=0,imax-1
  1251.             react(i,n)=0
  1252.          end do
  1253.       end do
  1254.  
  1255.       do la1=1,lmaxa
  1256.          @<Compute innermost sums@>
  1257.          do n=0,nmax-1
  1258.             do i=0,imax-1
  1259.                react(i,n)=react(i,n)+reactl(n)*legp(i,la1)
  1260.             end do
  1261.          end do
  1262.       end do
  1263.  
  1264.       do n=0,nmax-1
  1265.          do i=0,imax-1
  1266.             react(i,n)=react(i,n)/lam1a(i)
  1267.          end do
  1268.       end do
  1269.  
  1270.       return
  1271.       end
  1272.  
  1273. @ Workspace for |reactall| (|reactl| and |chila|) and for |potential|
  1274. (|fla| and |ijy|).
  1275. @<Index spec...@>=
  1276.       workalloc(nmax * 2 + nmax + (nmax1+1)*7*2)
  1277.  
  1278. @ Do the innermost two sums.
  1279.  
  1280. @<Compute innermost sums@>=
  1281.          do n=0,nmax-1
  1282.             reactl(n)=0
  1283.          end do
  1284.          do la=la1,lmaxa
  1285.             do n=0,nmax-1
  1286.                chila(n)=0
  1287.             end do
  1288.             do la2=1,la
  1289.                do n=0,nmax-1
  1290.                   chila(n)=chila(n)+hv(la,la1,la2)*chil(n,la2)
  1291.                end do
  1292.             end do
  1293.             call reaction(ua,du,c,fm,t,chila,nmax,nmax1,
  1294.      $           legjy(0,0,0,la),psid,ze,reactl,lf(la),work)
  1295.          end do
  1296.  
  1297. @* Inhomogeneous magnetic field.
  1298.  
  1299. @<Glob...@>=
  1300.       real eps,deltab               /* Inverse aspect ratio */
  1301.       external deltab           /* Variation of magnetic field */
  1302.  
  1303. @ Define magnetic field variation,
  1304. $$b=\frac{B(\phi)}{B(0)},\qquad \delta b=b-1,$$
  1305. where $\phi$ is the poloidal angle.  We assume that
  1306. $$b=\frac{1+\epsilon}{1+\epsilon\cos\phi};\qquad
  1307. \delta b=\frac{2\epsilon\sin^2(\phi/2)}{1+\epsilon\cos\phi}.$$
  1308.  
  1309. @<Functions...@>=
  1310.       function deltab(phi,eps)
  1311.  
  1312.       implicit_none
  1313.       real deltab,phi,eps
  1314.  
  1315.       deltab=2*eps*sin(phi/2)^2/(1+eps*cos(phi))
  1316.  
  1317.       return
  1318.       end
  1319.  
  1320. @ Arrays to hold various averaged quantities.
  1321.  
  1322.  
  1323. @<Glob...@>=
  1324.       integer kmax
  1325.       real lam1,lam2,lam1a,lam2g,harr
  1326.       dimension lam1a(0:imax-1),lam2g(0:imax),hv(lmaxa1,lmaxa1,lmaxa1)
  1327.       external lam1,lam2,hinit
  1328.  
  1329. @
  1330. @<Index decl...@>=
  1331.       integer ptr(lam1a),ptr(lam2g),ptr(harr)
  1332.  
  1333. @
  1334. @<Index spec...@>=
  1335.       alloc(lam1a,imax)
  1336.       alloc(lam2g,imax+1)
  1337.       alloc(harr,hind(lmaxa1,lmaxa1,lmaxa1))
  1338.  
  1339. @ Initialize these arrays.
  1340.  
  1341. @<Init...@>=
  1342.       do i=0,imax-1
  1343.          lam1a(i)=lam1(eps,th0a(i),kmax)
  1344.       end do
  1345.  
  1346.       do i=0,imax
  1347.          lam2g(i)=lam2(eps,th0g(i),kmax)
  1348.       end do
  1349.  
  1350.       call hinit(eps,kmax,lmaxa1,harr,work)
  1351.  
  1352. @ Define averages over the magnetic field.  We need three:
  1353. $$\eqalign{
  1354. \lambda_1&=\frac 1{2\pi} \int d\phi \frac{\cos\theta_0}{\cos\theta},\cr
  1355. \lambda_2&=\frac 1{2\pi}
  1356. \int \frac{d\phi}{b} \frac{\cos\theta}{\cos\theta_0},\cr
  1357. H_{l,l',l''}&=\frac 1{2\pi} \int d\phi\,b G_{l,l'} G_{l,l''},\cr
  1358. }$$
  1359. where
  1360. $$\sin^2\theta=b \sin^2\theta_0,$$
  1361. and hence
  1362. $$\cos\theta=\cos\theta_0\sqrt{1-\delta b\tan^2\theta_0}.$$
  1363. The following functions are specialized to the case of passing particles
  1364. only.
  1365.  
  1366. @ Define $\lambda_1$.
  1367.  
  1368. @<Functions...@>=
  1369.       function lam1(eps,th0,kmax)
  1370.  
  1371.       implicit_none
  1372.       integer kmax,k
  1373.       real lam1,eps,th0,phi,deltab,deltabv,sum,costh,pi
  1374.       external deltab
  1375.  
  1376.       pi=4*atan(const(1.0))
  1377.       sum=0
  1378.       do k=0,kmax-1
  1379.          phi=2*pi*(k+const(0.25))/kmax
  1380.          deltabv=deltab(phi,eps)
  1381.          costh=sqrt(1-min(const(1.0),deltabv*tan(th0)^2))
  1382.          sum=sum+1/costh
  1383.       end do
  1384.       lam1=sum/kmax
  1385.  
  1386.       return
  1387.       end
  1388.  
  1389. @ Define $\lambda_2$.
  1390.  
  1391. @<Functions...@>=
  1392.       function lam2(eps,th0,kmax)
  1393.  
  1394.       implicit_none
  1395.       integer kmax,k
  1396.       real lam2,eps,th0,phi,deltab,deltabv,sum,costh,pi
  1397.       external deltab
  1398.  
  1399.       pi=4*atan(const(1.0))
  1400.       sum=0
  1401.       do k=0,kmax-1
  1402.          phi=2*pi*(k+const(0.25))/kmax
  1403.          deltabv=deltab(phi,eps)
  1404.          costh=sqrt(1-min(const(1.0),deltabv*tan(th0)^2))
  1405.          sum=sum+costh/(1+deltabv)
  1406.       end do
  1407.       lam2=sum/kmax
  1408.  
  1409.       return
  1410.       end
  1411.  
  1412. @ Define $H_{l,l',l''}$ via
  1413. $$
  1414.   H_{l,l',l''}=\frac{2l+1}{2l''+1}
  1415. \lave{ b G_{l,l'} G_{l,l''}}.
  1416. $$
  1417.  
  1418. |gv| allows us to index into |garr| conveniently.  Enough space is allowed
  1419. to accomodate |gv(la,0)|, |gv(la,la+1)|, and |gv(la,la+2)|.  These can be
  1420. initialized to $0$ thereby simplifying the recursion for $G$.
  1421.  
  1422. $H$ is defined out to |lmaxa1| because we need $H_{1,1,1}$ even when
  1423. $l_{\rm max}=0$.
  1424.  
  1425. @<Functions...@>=
  1426.       subroutine hinit(eps,kmax,lmaxa1,harr,garr)
  1427.  
  1428.       implicit_none
  1429.       integer kmax,k,lmaxa1,la,la1,la2,l,l1
  1430.       real harr,eps,phi,deltab,b,pi,garr
  1431.       dimension hv(lmaxa1,lmaxa1,lmaxa1)
  1432.       dimension gv(lmaxa1,lmaxa1)
  1433.       external deltab
  1434.  
  1435.       pi=4*atan(const(1.0))
  1436.  
  1437.       @<Set initialial values for |harr| and |garr|@>
  1438.  
  1439.       do k=0,kmax-1
  1440.          phi=2*pi*(k+const(0.25))/kmax
  1441.          b=1+deltab(phi,eps)
  1442.          @<Fill |garr|@>
  1443.          do la=1,lmaxa1
  1444.             do la1=1,la
  1445.                do la2=1,la
  1446.                   hv(la,la1,la2)=hv(la,la1,la2)+b*gv(la,la1)*gv(la,la2)
  1447.                end do
  1448.             end do
  1449.          end do
  1450.       end do
  1451.  
  1452.       do la=1,lmaxa1
  1453.          do la1=1,la
  1454.             do la2=1,la
  1455.                hv(la,la1,la2)=(2*lf(la)+1)/areal(2*lf(la2)+1)*
  1456.      $              hv(la,la1,la2)/kmax
  1457.             end do
  1458.          end do
  1459.       end do
  1460.  
  1461.       return
  1462.       end
  1463.  
  1464. @ Workspace for |hinit| (|garr|).
  1465. @<Index spec...@>=
  1466.       workalloc(gind(lmaxa1,lmaxa1))
  1467.  
  1468. @ Initialize |harr| and set the edge values of |garr| to zero.
  1469.  
  1470. @<Set initialial values for |harr| and |garr|@>=
  1471.       do la=1,lmaxa1
  1472.          do la1=1,la
  1473.             do la2=1,la
  1474.                hv(la,la1,la2)=0
  1475.             end do
  1476.          end do
  1477.       end do
  1478.  
  1479.       do la=-2,lmaxa1-1
  1480.          gv(la,0)=0
  1481.       end do
  1482.       do la=-1,lmaxa1-1
  1483.          gv(la,la+1)=0
  1484.          gv(la,la+2)=0
  1485.       end do
  1486.       gv(1,1)=1
  1487.  
  1488. @ Use the recursion relation for $G$ to fill |garr|.
  1489.  
  1490. @<Fill |garr|@>=
  1491.       do la=2,lmaxa1
  1492.          l=lf(la)
  1493.          do la1=1,la
  1494.             l1=lf(la1)
  1495.             gv(la,la1)=(2*(2*l-3)*(l^2-3*l+1)*gv(la-1,la1) - @|
  1496.      $           (l-3)*(l-2)*(2*l-1)*gv(la-2,la1)) / (l*(l-1)*(2*l-5)) + @|
  1497.      $           (2*l-3)*(2*l-1)*b*
  1498.      $           ( (l1+1)*(l1+2) * gv(la-1,la1+1)/ ((2*l1+3)*(2*l1+5)) - @|
  1499.      $           2*(l1^2+l1-1) * gv(la-1,la1)/((2*l1-1)*(2*l1+3)) + @|
  1500.      $           l1*(l1-1) * gv(la-1,la1-1)/((2*l1-3)*(2*l1-1)) )/(l*(l-1))
  1501.          end do
  1502.       end do
  1503.  
  1504. @* Residue calculation.  The array |resid| is already initialized with the
  1505. reaction term.  Two methods for the calculation are given here: the
  1506. straightforward coding of the residue term, which is slow but easy to
  1507. check; and a faster method using the arrays |uinv| and |th0inv| which are
  1508. used in the tridiagonal elimination.
  1509.  
  1510. @m RESIDUE 0 /* Should we calculate the residue in the straightforward way? */
  1511.  
  1512. @<Functions...@>=
  1513. @#if RESIDUE
  1514.       subroutine residue(du,ua,ug,nmax,dth0,th0a,th0g,csth0a,imax,imax1,
  1515.      $    chi,duug,fu,dtt,c,lam1a,lam2g,rho,resid)
  1516.  
  1517.       implicit_none
  1518.       integer nmax,imax,imax1,n,i
  1519.       real du,ua,ug,dth0,th0a,th0g,csth0a,chi,duug,fu,dtt,c,
  1520.      $     lam1a,lam2g,rho,resid
  1521.       dimension ua(0:nmax-1),ug(0:nmax),th0a(0:imax-1),th0g(0:imax),
  1522.      $     csth0a(0:imax-1),
  1523.      $     chi(0:imax1-1,0:nmax-1),duug(0:nmax),fu(0:nmax-1),dtt(0:nmax-1),
  1524.      $     lam1a(0:imax-1),lam2g(0:imax),resid(0:imax1-1,0:nmax-1)
  1525.  
  1526.       @<Energy diffusion term@>
  1527.  
  1528.       @<Friction term@>
  1529.  
  1530.       @<Pitch-angle scattering term@>
  1531.  
  1532.       @<Electric field term@>
  1533.  
  1534.  /* Normalize to pitch-angle diffusion coefficient. */
  1535.       do n=0,nmax-1
  1536.          do i=0,imax-1
  1537.             resid(i,n)=resid(i,n)*ua(n)^2/dtt(n)
  1538.          end do
  1539.       end do
  1540.  
  1541.       return
  1542.       end
  1543. @#endif
  1544.  
  1545. @ The faster way.
  1546.  
  1547. @<Functions...@>=
  1548. @#if !RESIDUE
  1549. @#if VAX
  1550.       options /check=nobounds
  1551. @#endif
  1552.  
  1553.       subroutine residue(ua,nmax,nmax1,csth0a,imax,imax1,chi,dtt,c,lam1a,
  1554.      $    uinv,th0inv,resid)
  1555.  
  1556.       implicit_none
  1557.       integer nmax,nmax1,imax,imax1,n,i
  1558.       real ua,csth0a,chi,dtt,c,lam1a,resid,uinv,th0inv
  1559.       dimension ua(0:nmax-1),chi(0:imax1-1,0:nmax-1),csth0a(0:imax-1),
  1560.      $     dtt(0:nmax-1),lam1a(0:imax-1),resid(0:imax1-1,0:nmax-1),
  1561.      $     uinv(0:nmax1-1,-1:1),th0inv(0:imax1-1,-1:1)
  1562.  
  1563.       @<Electric field term@>
  1564.  
  1565.  /* Normalize to pitch-angle diffusion coefficient and add in
  1566.     differential terms. */
  1567.       do n=0,nmax-1
  1568.          do i=0,imax-1
  1569.             resid(i,n)=resid(i,n)*ua(n)^2/dtt(n)+ @|
  1570.      $           chi(i,n-1)*uinv(n,-1)+chi(i,n)*uinv(n,0)+
  1571.      $           chi(i,n+1)*uinv(n,1)+ @|
  1572.      $           chi(i-1,n)*th0inv(i,-1)+chi(i,n)*th0inv(i,0)+
  1573.      $           chi(i+1,n)*th0inv(i,1)
  1574.          end do
  1575.       end do
  1576.  
  1577.       return
  1578.       end
  1579. @#endif
  1580.  
  1581. @ Calculate contributions to the residue from the energy diffusion term
  1582. $$\frac{1}{u^2}\frac{\d}{\d u} u^2 D_{uu} \frac{\d \chi}{\d u}.$$
  1583. Boundary at $u=0$ takes care of itself.  Boundary at $u=u_{\rm max}$
  1584. handled by specifying
  1585. |chi(i,nmax)=chi(i,nmax-1)+rho*(chi(i,nmax-1)-chi(i,nmax-2))|.  For
  1586. $\rho=1$, we have $\chi''(u_{\rm max})=0$, and for $\rho=0$, we have
  1587. $\chi'(u_{\rm max})=0$.
  1588.  
  1589. @<Energy diffusion term@>=
  1590.       do i=0,imax-1
  1591.          n=0
  1592.          resid(i,n)=resid(i,n) + @|
  1593.      $        (ug(n+1)^2*duug(n+1)*(chi(i,n+1)-chi(i,n))/du)/(ua(n)^2*du)
  1594.          do n=1,nmax-2
  1595.             resid(i,n)=resid(i,n) + @|
  1596.      $           (ug(n+1)^2*duug(n+1)*(chi(i,n+1)-chi(i,n))/du - @|
  1597.      $           ug(n)^2*duug(n)*(chi(i,n)-chi(i,n-1))/du)/(ua(n)^2*du)
  1598.          end do
  1599.          n=nmax-1
  1600.          resid(i,n)=resid(i,n) + @|
  1601.      $        (ug(n+1)^2*duug(n+1)*rho*(chi(i,n)-chi(i,n-1))/du - @|
  1602.      $        ug(n)^2*duug(n)*(chi(i,n)-chi(i,n-1))/du)/(ua(n)^2*du)
  1603.       end do
  1604.  
  1605. @ Calculate contributions to the residue from the friction term
  1606. $$F_{u} \frac{\d \chi}{\d u}.$$
  1607. Boundary at $u=0$ handled by assuming $\chi$ is odd in $u$, i.e.,
  1608. |chi(i,-1)=-chi(i,0)|.  Boundary at $u=u_{\rm max}$ handled in the same way
  1609. as in the calculation of the energy diffusion term.
  1610.  
  1611. @<Friction term@>=
  1612.       do i=0,imax-1
  1613.          n=0
  1614.          resid(i,n)=resid(i,n)+fu(n)*(chi(i,n+1)+chi(i,n))/(2*du)
  1615.          do n=1,nmax-2
  1616.             resid(i,n)=resid(i,n)+fu(n)*(chi(i,n+1)-chi(i,n-1))/(2*du)
  1617.          end do
  1618.          n=nmax-1
  1619.          resid(i,n)=resid(i,n)+fu(n)*(1+rho)*(chi(i,n)-chi(i,n-1))/(2*du)
  1620.       end do
  1621.  
  1622. @ Calculate contributions to the residue from the pitch-angle scattering
  1623. term
  1624. $$\frac{D_{\theta\theta}}{u^2}
  1625. \frac{1}{\lambda_1\sin\theta_0}\frac{\d}{\d\theta_0} \sin\theta_0 \lambda_2
  1626. \frac{\d}{\d\theta_0}.$$
  1627. Boundary at $\theta_0=0$ takes care of itself.  At $\theta_{0,\rm max}
  1628. =\theta_t$, assume that $\chi=0$.
  1629.  
  1630. @<Pitch-angle scattering term@>=
  1631.       do n=0,nmax-1
  1632.          i=0
  1633.          resid(i,n)=resid(i,n)+dtt(n)/ua(n)^2 * @|
  1634.      $        (sin(th0g(i+1))*lam2g(i+1)*(chi(i+1,n)-chi(i,n))/dth0)/
  1635.      $        (lam1a(i)*sin(th0a(i))*dth0)
  1636.          do i=1,imax-2
  1637.             resid(i,n)=resid(i,n)+dtt(n)/ua(n)^2 * @|
  1638.      $           (sin(th0g(i+1))*lam2g(i+1)*(chi(i+1,n)-chi(i,n))/dth0 - @|
  1639.      $           sin(th0g(i))*lam2g(i)*(chi(i,n)-chi(i-1,n))/dth0)/
  1640.      $           (lam1a(i)*sin(th0a(i))*dth0)
  1641.          end do
  1642.          i=imax-1
  1643.          resid(i,n)=resid(i,n)+dtt(n)/ua(n)^2 * @|
  1644.      $        (sin(th0g(i+1))*lam2g(i+1)*(-chi(i,n))/(dth0/2) - @|
  1645.      $        sin(th0g(i))*lam2g(i)*(chi(i,n)-chi(i-1,n))/dth0)/
  1646.      $        (lam1a(i)*sin(th0a(i))*dth0)
  1647.       end do
  1648.  
  1649. @ Finally add in the electric field term:
  1650. $$\frac{v \cos\theta_0}{\lambda_1}. $$
  1651.  
  1652. @<Electric field term@>=
  1653.       do n=0,nmax-1
  1654.          do i=0,imax-1
  1655.             resid(i,n)=resid(i,n)+
  1656.      $           csth0a(i)/lam1a(i)*ua(n)/sqrt(1+(ua(n)/c)^2)
  1657.          end do
  1658.       end do
  1659.  
  1660. @ Calculate norm of residue.
  1661.  
  1662. @<Functions...@>=
  1663.       subroutine error(du,ua,umax,nmax,dth0,th0a,th0max,imax,imax1,resid,chi,
  1664.      $    abserr,relerr,aerr,rerr)
  1665.  
  1666.       implicit_none
  1667.       integer nmax,imax,imax1,i,n
  1668.       real du,ua,umax,dth0,th0a,th0max,resid,chi,abserr,relerr
  1669.       dimension ua(0:nmax-1),th0a(0:imax-1),resid(0:imax1-1,0:nmax-1),
  1670.      $     chi(0:imax1-1,0:nmax-1)
  1671.       real aerr,rerr
  1672.       dimension aerr(0:imax-1),rerr(0:imax-1)
  1673.  
  1674.       do i=0,imax-1
  1675.          aerr(i)=0
  1676.          rerr(i)=0
  1677.       end do
  1678.  
  1679.       do n=0,nmax-1
  1680.          do i=0,imax-1
  1681.             aerr(i)=aerr(i)+resid(i,n)^2*ua(n)^2
  1682.             rerr(i)=rerr(i)+(resid(i,n)/max(epsilon,abs(chi(i,n))))^2*ua(n)^2
  1683.          end do
  1684.       end do
  1685.  
  1686.       abserr=0
  1687.       relerr=0
  1688.       do i=0,imax-1
  1689.          abserr=abserr+sin(th0a(i))*aerr(i)
  1690.          relerr=relerr+sin(th0a(i))*rerr(i)
  1691.       end do
  1692.  
  1693.  /* Normalize to total volume of velocity space */
  1694.       abserr=sqrt(abserr*du*dth0/(umax^3/3*(1-cos(th0max))))
  1695.       relerr=sqrt(relerr*du*dth0/(umax^3/3*(1-cos(th0max))))
  1696.  
  1697.       return
  1698.       end
  1699.  
  1700. @ Workspace for |error| (|aerr| and |rerr|).
  1701. @<Index spec...@>=
  1702.       workalloc(2*imax)
  1703.  
  1704. @* Matrices for inversion.
  1705.  
  1706. @<Glob...@>=
  1707.       real uinv,th0inv,rho
  1708.       dimension uinv(0:nmax1-1,-1:1),th0inv(0:imax1-1,-1:1)
  1709.       external matrixinit
  1710.  
  1711. @
  1712. @<Index decl...@>=
  1713.       integer ptr(uinv),ptr(th0inv)
  1714.  
  1715. @
  1716. @<Index spec...@>=
  1717.       alloc(uinv,nmax1*3)
  1718.       alloc(th0inv,imax1*3)
  1719.  
  1720. @ Initialize matrices.
  1721.  
  1722. @<Init...@>=
  1723.       call matrixinit(du,ua,ug,nmax,nmax1,dth0,th0a,th0g,imax,imax1,
  1724.      $    duug,fu,dtt,lam1a,lam2g,uinv,th0inv,rho)
  1725.  
  1726. @ Calculate inversion matrices.  These have to be compatible with
  1727. subroutine |residue|.
  1728.  
  1729. @<Functions...@>=
  1730.       subroutine matrixinit(du,ua,ug,nmax,nmax1,dth0,th0a,th0g,imax,imax1,
  1731.      $    duug,fu,dtt,lam1a,lam2g,uinv,th0inv,rho)
  1732.  
  1733.       implicit_none
  1734.       integer nmax,nmax1,imax,imax1,n,i
  1735.       real du,ua,ug,dth0,th0a,th0g,duug,fu,dtt,lam1a,lam2g,
  1736.      $     uinv,th0inv,rho
  1737.       dimension ua(0:nmax-1),ug(0:nmax),th0a(0:imax-1),th0g(0:imax),
  1738.      $     duug(0:nmax),fu(0:nmax-1),dtt(0:nmax-1),
  1739.      $     lam1a(0:imax-1),lam2g(0:imax),
  1740.      $     uinv(0:nmax1-1,-1:1),th0inv(0:imax1-1,-1:1)
  1741.  
  1742.       @<Matrices for $u$ inversion@>
  1743.  
  1744.       @<Matrices for $\theta_0$ inversion@>
  1745.  
  1746.       return
  1747.       end
  1748.  
  1749. @ Define matrices for inversion of diffusion and friction operator.  These
  1750. are one-dimensional because the operator is independent of $\theta_0$.
  1751.  
  1752. @<Matrices for $u$ inversion@>=
  1753.       do n=0,nmax-1
  1754.          uinv(n,-1)=ug(n)^2*duug(n)/(ua(n)^2*du^2)
  1755.          uinv(n,1)=ug(n+1)^2*duug(n+1)/(ua(n)^2*du^2)
  1756.          uinv(n,0)=-uinv(n,-1)-uinv(n,1)
  1757.          uinv(n,-1)=uinv(n,-1)-fu(n)/(2*du)
  1758.          uinv(n,1)=uinv(n,1)+fu(n)/(2*du)
  1759.       end do
  1760.       n=0                       /* Odd at $u=0$ */
  1761.       uinv(n,0)=uinv(n,0)-uinv(n,-1)
  1762.       uinv(n,-1)=0
  1763.       n=nmax-1                  /* Apply boundary condition at $u_{\rm max}$ */
  1764.       uinv(n,-1)=uinv(n,-1)-rho*uinv(n,1)
  1765.       uinv(n,0)=uinv(n,0)+(1+rho)*uinv(n,1)
  1766.       uinv(n,1)=0
  1767.  
  1768.       do n=0,nmax-1
  1769.          uinv(n,-1)=uinv(n,-1)*ua(n)^2/dtt(n)
  1770.          uinv(n,0)=uinv(n,0)*ua(n)^2/dtt(n)
  1771.          uinv(n,1)=uinv(n,1)*ua(n)^2/dtt(n)
  1772.       end do
  1773.  
  1774. @ Define matrices for inversion of pitch-angle scattering operator.  These
  1775. are one-dimensional because, after divided out $D_{\theta\theta,0}/u^2$,
  1776. the operator is independent of $u$.
  1777.  
  1778. @<Matrices for $\theta_0$ inversion@>=
  1779.       do i=0,imax-1
  1780.          th0inv(i,-1)=sin(th0g(i))*lam2g(i)/(lam1a(i)*sin(th0a(i))*dth0^2)
  1781.          th0inv(i,1)=sin(th0g(i+1))*lam2g(i+1)/(lam1a(i)*sin(th0a(i))*dth0^2)
  1782.          th0inv(i,0)=-th0inv(i,-1)-th0inv(i,1)
  1783.       end do
  1784.       i=0                       /* Nothing special needs to be done */
  1785.       i=imax-1                  /* Zero on trapped passing boundary */
  1786.       th0inv(i,0)=th0inv(i,0)-th0inv(i,1)
  1787.       th0inv(i,1)=0
  1788.  
  1789. @ Solve the tridiagonal equations.
  1790.  
  1791. This subroutine solves the tridiagonal equation
  1792. $$
  1793. x_i-\alpha\Delta t(a_i x_{i-1}+b_i x_i+c_i x_{i+1})=z_i,
  1794. $$
  1795. for $0\le i< n$, with $a_0=c_{n-1}=0$.
  1796. Vectorized to handle $m$ parallel systems.  |ms| is the skipping distance
  1797. in the vectorizing direction.  |ns| is the skipping distance in the
  1798. solution direction between $x_i$ and $x_{i+1}$.  In this version, |a|, |b|, and
  1799. |c| are the same for each system.
  1800.  
  1801. Avoid using any working storage by clobbering |z| and using |x| as a
  1802. temporary.
  1803.  
  1804. @<Functions...@>=
  1805. @#if VAX
  1806.       options /check=nobounds
  1807. @#endif
  1808.  
  1809.       subroutine solve(x,ns,n,ms,m,a,b,c,z,dt,alpha)
  1810.  
  1811.       implicit_none
  1812.       integer n,ns,m,ms,i,k
  1813.       real x,a,b,c,z,dt,alpha,dt2,den
  1814.       dimension x(0:ms-1,0:*),z(0:ms-1,0:*),a(0:n-1),b(0:n-1),c(0:n-1)
  1815.  
  1816.       dt2=-alpha*dt
  1817.  
  1818.       i=0
  1819.       do k=0,m-1
  1820.          den=1+dt2*b(i)
  1821.          x(ns*i,k)=z(ns*i,k)/den
  1822.          z(ns*i,k)=-dt2*c(i)/den
  1823.       end do
  1824.  
  1825.       do i=1,n-2
  1826.          do k=0,m-1
  1827.             den=1+dt2*(b(i)+a(i)*z(ns*(i-1),k))
  1828.             x(ns*i,k)=(z(ns*i,k)-dt2*a(i)*x(ns*(i-1),k))/den
  1829.             z(ns*i,k)=-dt2*c(i)/den
  1830.          end do
  1831.       end do
  1832.  
  1833.       i=n-1
  1834.       do k=0,m-1
  1835.          den=1+dt2*(b(i)+a(i)*z(ns*(i-1),k))
  1836.          x(ns*i,k)=(z(ns*i,k)-dt2*a(i)*x(ns*(i-1),k))/den
  1837.          z(ns*i,k)=0
  1838.       end do
  1839.  
  1840.  
  1841.  /* The equations have now been converted to the form $x_i=r_i x_{i+1}+s_i$
  1842.  (with $r=y$, $s=x$). */
  1843.  
  1844.       do i=n-2,0,-1
  1845.          do  k=0,m-1
  1846.             x(ns*i,k)=z(ns*i,k)*x(ns*(i+1),k)+x(ns*i,k)
  1847.          end do
  1848.       end do
  1849.  
  1850.       return
  1851.       end
  1852.  
  1853. @* Time advancement.
  1854.  
  1855. @<Glob...@>=
  1856.       integer tmax,time,tskip
  1857.       real resid,abserr,relerr,alpha,dt,resida
  1858.       dimension resid(0:imax1-1,0:nmax-1),resida(0:imax1-1,0:nmax-1)
  1859.       external decomp,reactall,residue,error,solve
  1860.  
  1861. @
  1862. @<Index decl...@>=
  1863.       integer ptr(resid),ptr(resida)
  1864.  
  1865. @
  1866. @<Index spec...@>=
  1867.       alloc(resid,imax1*nmax)
  1868.       alloc(resida,imax1*nmax)
  1869.  
  1870. @ Calculate reaction term.
  1871.  
  1872. @<Make a step@>=
  1873.       call decomp(chi,nmax,nmax1,imax,imax1,lmaxa,lmaxa1,th0a,dth0,legp,chil)
  1874.       call reactall(ua,du,c,fm,t,chil,nmax,nmax1,imax,imax1,lam1a,
  1875.      $     legjy(0,0,0,1),psid,legp,harr,ze,lmaxa,lmaxa1,resid,
  1876.      $     work(0),work(nmax),work(2*nmax))
  1877.  
  1878. @ Calculate residue and its norm.
  1879.  
  1880. @<Make a step@>=
  1881. @#if RESIDUE
  1882.       call residue(du,ua,ug,nmax,dth0,th0a,th0g,csth0a,imax,imax1,chi,
  1883.      $    duug,fu,dtt,c,lam1a,lam2g,rho,resid)
  1884. @#else
  1885.       call residue(ua,nmax,nmax1,csth0a,imax,imax1,chi,dtt,c,lam1a,
  1886.      $    uinv,th0inv,resid)
  1887. @#endif
  1888.       if (mod(time,tskip)==0) then
  1889.          call error(du,ua,umax,nmax,dth0,th0a,th0max,imax,imax1,resid,chi,
  1890.      $        abserr,relerr,work(0),work(imax))
  1891.       end if
  1892.  
  1893. @ Advance $\chi$.
  1894.  
  1895. @<Make a step@>=
  1896.       call solve(resida,imax1,nmax,1,imax,uinv(0,-1),uinv(0,0),uinv(0,1),
  1897.      $    resid,dt,alpha)
  1898.       call solve(resid,1,imax,imax1,nmax,th0inv(0,-1),th0inv(0,0),th0inv(0,1),
  1899.      $    resida,dt,alpha)
  1900.  
  1901.       do n=0,nmax-1
  1902.          do i=0,imax-1
  1903.             chi(i,n)=chi(i,n)+dt*resid(i,n)
  1904.          end do
  1905.       end do
  1906.  
  1907. @* Current and conductivity.
  1908.  
  1909. @<Glob...@>=
  1910.       real curv,current,cond,e
  1911.       external current
  1912.  
  1913. @ Compute current and conductivity.  The conductivity is define as
  1914. $J_{0\parallel}/E_{0\parallel}$ where
  1915. $$E_{0\parallel} = B_0\frac{\int E_{\parallel} dl}{\int B\,dl}.$$
  1916. Substituting $E_\parallel = (B_\zeta/B) \Phi/(2\pi R)$ and $\Phi=TQ/L$ gives
  1917. $E_\parallel = T/\int b \,dl/L$.
  1918.  
  1919. @<Make a step@>=
  1920.       if (mod(time,tskip)==0) then
  1921.          curv=current(du,ua,c,nmax,dth0,th0a,imax,imax1,fm,chi,work)
  1922.          e=t/hv(1,1,1)
  1923.          cond=curv*zi/(t*sqrt(t)*e)
  1924.          write(outunit,*) time,cond,abserr,relerr
  1925.       end if
  1926.  
  1927. @ Function to calculate current.
  1928.  
  1929. @<Functions...@>=
  1930.       function current(du,ua,c,nmax,dth0,th0a,imax,imax1,fm,chi,cur)
  1931.  
  1932.       implicit_none
  1933.       integer nmax,imax,imax1,n,i
  1934.       real current,du,ua,c,dth0,th0a,fm,chi
  1935.       dimension ua(0:nmax-1),th0a(0:imax-1),
  1936.      $     fm(0:nmax-1),chi(0:imax1-1,0:nmax-1)
  1937.       real cur,pi
  1938.       dimension cur(0:imax-1)
  1939.  
  1940.       pi=4*atan(const(1.0))
  1941.       do i=0,imax-1
  1942.          cur(i)=0
  1943.       end do
  1944.  
  1945.       do n=0,nmax-1
  1946.          do i=0,imax-1
  1947.             cur(i)=cur(i)+chi(i,n)*fm(n)*ua(n)**3/sqrt(1+(ua(n)/c)^2)
  1948.          end do
  1949.       end do
  1950.  
  1951.       current=0
  1952.       do i=0,imax-1
  1953.          current=current+sin(th0a(i))*cos(th0a(i))*cur(i)
  1954.       end do
  1955.  
  1956.       current=4*pi*du*dth0*current
  1957.  
  1958.       return
  1959.       end
  1960.  
  1961. @ Workspace for |current| (|cur|).
  1962. @<Index spec...@>=
  1963.       workalloc(imax)
  1964.  
  1965. @* Write out results to disk.
  1966.  
  1967. @<Write out results@>=
  1968.       write(diskunit) nmax,imax,kmax,lmax
  1969.       write(diskunit) single(t),single(c2),single(ze),single(zi),single(eps)
  1970.       write(diskunit) single(umax),single(th0max),single(du),single(dth0),
  1971.      $     single(rho)
  1972.       write(diskunit) single(dt),tmax,single(alpha)
  1973.       write(diskunit) single(cond),single(abserr),single(relerr)
  1974.       write(diskunit) (single(ua(n)),n=0,nmax-1)
  1975.       write(diskunit) (single(ug(n)),n=0,nmax)
  1976.       write(diskunit) (single(th0a(n)),n=0,imax-1)
  1977.       write(diskunit) (single(th0g(n)),n=0,imax)
  1978.       write(diskunit) (single(fm(n)),n=0,nmax-1)
  1979.       write(diskunit) ((single(chi(i,n)),i=0,imax-1),n=0,nmax-1)
  1980.  
  1981. @* Legendre functions.  It is convenient to express the potentials in terms
  1982. of a set of functions defined by
  1983. $$
  1984. \eqalignno{
  1985. j\subb l1a(z) &=\sqrt{\frac{\pi}{2z}}P^{-l-1/2}_{a-1/2}(\sqrt{1+z^2}),\cr
  1986. y\subb l1a(z) &=(-1)^{l+1}\sqrt{\frac{\pi}{2z}}P^{l+1/2}_{a-1/2}(\sqrt{1+z^2}),
  1987. \cr}
  1988. $$
  1989. where $P^\mu_\nu$ is the associated Legendre function of the first kind.
  1990. Multiple index functions are defined recursively by
  1991. $$
  1992. j\subb l{k+2}{\s aa'} =
  1993. \cases{
  1994.   \displaystyle\frac{j\subb l{k+1}{\s a}-j\subb l{k+1}{\s a'}}
  1995.     {a^2-a'^2},&for $a\ne a'$,\cr
  1996.   \displaystyle\pd{j\subb l{k+1}{\s a}}{(a^2)},
  1997.     &for $a=a'$,\cr
  1998. }$$
  1999. with $y\subb lk\s$ defined in a similar fashion.
  2000. The two families of functions are related by
  2001. $$y\subb lk{\s}=(-1)^{l+1}j\subb {-l-1}k{\s}.$$
  2002.  
  2003. In fact we shall work with two derived functions, scaled Legendre functions
  2004. $\ja{l,a}(z)$ defined by
  2005. $$j\subb l1a(z) = \frac{z^l}{(2l+1)!!} \ja{l,a}(z),$$
  2006. and normalized Legendre functions defined by
  2007. $$ \jn lk{\s}(u) = c^{2k+l-2} j\subb lk{\s}(u/c). $$
  2008. For $k=1$, we have
  2009. $$\jn\subb l1a(z) = \frac{u^l}{(2l+1)!!} \ja{l,a}(u/c).$$
  2010.  
  2011. The methods used for computing these functions are given in the appendix.
  2012.  
  2013. @ Scaled Legendre functions.  This subroutine returns the scaled Legendre
  2014. functions $\hbox{|jarray(l,a)|}=\ja{l,a}(z)$ for $-|lmax|-1 \le l \le
  2015. |lmax|$ and $0\le a \le |amax|$.
  2016.  
  2017. @<Functions...@>=
  2018.       subroutine legendrejs(z,lmax,amax,jarray,lmax1)
  2019.  
  2020.       implicit_none
  2021.       integer l,a,lmax,amax,lmax1,lstart
  2022.       real z,jarray,z2,g,ja0,ja1,ja2,ratio,sigma
  2023.       dimension jarray(-lmax1-1:lmax1,0:amax)
  2024.  
  2025.       if (amax<0 || lmax<0) return /* Nothing to do! */
  2026.       if (lmax>lmax1) return /* Error: not enough room! */
  2027.  
  2028.       z2=z^2
  2029.       g=sqrt(1+z2)
  2030.  
  2031.       @< Do the cases $-a\le l<a$ @>
  2032.  
  2033.       @< Do the cases $l<-a$ @>
  2034.  
  2035.       @< Do the cases $l\ge0$, $a=0$ @>
  2036.  
  2037.       @< Do the other cases, i.e., $a>0$, $l\ge a$ @>
  2038.  
  2039.       return
  2040.       end
  2041.  
  2042. @ Calculate the scaled Legendre functions for the easy case, namely $-a\le
  2043. l<a$.
  2044.  
  2045. @< Do the cases $-a\le l<a$ @>=
  2046.  
  2047.       do a=1,amax               /* $a=0$ is excluded */
  2048.          ja2=1                  /* $\ja{a-1,a}$ */
  2049.          ja1=g                  /* $\ja{a-2,a}$ */
  2050.          do l=a-3,lmax-1,-1 @/
  2051.  /* Get things started by iterating down to $|lmax|-1$ if need be.
  2052.  This is from equation (A29) */
  2053.             ja0=g*ja1-z2*(l-a+2)*(l+a+2)*ja2/((2*l+3)*(2*l+5))
  2054.             ja2=ja1             /* $|ja2| = \ja{l+1,a}$ */
  2055.             ja1=ja0             /* $|ja1| = \ja{l,a}$ */
  2056.          end do
  2057.          l=min(lmax,a-1)
  2058.          jarray(l,a)=ja2
  2059.          l=l-1
  2060.          jarray(l,a)=ja1
  2061.          do l=min(lmax,a-1)-2,max(-a,-lmax-1),-1 @/
  2062.  /* Main iteration loop---again from equation (A29) */
  2063.             jarray(l,a)=g*jarray(l+1,a)-
  2064.      $           z2*(l-a+2)*(l+a+2)*jarray(l+2,a)/((2*l+3)*(2*l+5))
  2065.          end do
  2066.       end do
  2067.  
  2068. @ Calculate the scaled Legendre functions for the other easy case, namely
  2069. $l<-a$.
  2070.  
  2071. @< Do the cases $l<-a$ @>=
  2072.  
  2073.       do a=0,min(amax,lmax)
  2074.          l=-a-1
  2075.          jarray(l,a)=1
  2076.          l=l-1
  2077.          if (l>=-lmax-1) then
  2078.             jarray(l,a)=g
  2079.          end if
  2080.          do l=-a-3,-lmax-1,-1 @/
  2081.  /* Main iteration loop---again from equation (A29) */
  2082.             jarray(l,a)=g*jarray(l+1,a)-
  2083.      $           z2*(l-a+2)*(l+a+2)*jarray(l+2,a)/((2*l+3)*(2*l+5))
  2084.          end do
  2085.       end do
  2086.  
  2087. @ Calculate $\ja{l\ge0,0}$.  Depending on the magnitude of the argument we
  2088. either use backwards recursion (for $z \le |lmax|+1$) or forwards
  2089. recursion using $\ja{-1,0}=1$ and $\ja{0,0} = (\sinh^{-1} z)/z$.
  2090.  
  2091. @< Do the cases $l\ge0$, $a=0$ @>=
  2092.       a = 0
  2093.       if (abs(z) <= lmax+1) then @/
  2094.  /* Estimate where to start the recursion.  The 10 is a extra guard. */
  2095.          lstart = lmax + log(epsilon)/(2*log((epsilon+abs(z))/(g+1))) + 10 @/
  2096.  /* Initial guess for ratio $\ja{L'+1,a}/\ja{L',a}$. */
  2097.          ratio = 2/(g+1)
  2098.          do l=lstart,lmax-1,-1
  2099.             ratio=1/(g - z2*(l-a+2)*(l+a+2)*ratio/((2*l+3)*(2*l+5))) @/
  2100.  /* At this point, |ratio| is approximation for $\ja{l+1,a}/\ja{l,a}$. */
  2101.          end do
  2102.          jarray(lmax,a)=ratio
  2103.          ja0=1
  2104.          do l=lmax-2,-1,-1
  2105.             jarray(l+1,a)=ja0
  2106.             ja0=g*jarray(l+1,a)-
  2107.      $           z2*(l-a+2)*(l+a+2)*jarray(l+2,a)/((2*l+3)*(2*l+5))
  2108.          end do
  2109.          ja0=1/ja0
  2110.          do l=0,lmax
  2111.             jarray(l,a)=ja0*jarray(l,a)
  2112.          end do
  2113.       else
  2114.          /* Use forward recurrence for $z>|lmax|+1$. */
  2115.          sigma=log(g+abs(z))        /* $\sinh^{-1}(\abs z)$ */
  2116.          l=0
  2117.          jarray(l,a)=sigma/abs(z)   /* Starting value.  We assume
  2118.              that $\ja{-1,0}$ has already been set to $1$. */
  2119.          do l=1,lmax @/
  2120.  /* Equation (A29) */
  2121.             jarray(l,a)=(g*jarray(l-1,a)-jarray(l-2,a))*
  2122.      $           (2*l-1)*(2*l+1)/(z2*(l-a)*(l+a))
  2123.          end do
  2124.       end if
  2125.  
  2126. @ Do the other cases, i.e., $a>0$, $l\ge a$.
  2127.  
  2128. @< Do the other cases, i.e., $a>0$, $l\ge a$ @>=
  2129.       do a=1,min(lmax,amax)
  2130.          l=lmax @/
  2131.  /* Initialize backwards recursion using equation (A30). */
  2132.          jarray(l,a)=((2*l+1)*jarray(l-1,a-1)-
  2133.      $    (l+1-a)*g*jarray(l,a-1))/(l+a)
  2134.          l=lmax-1
  2135.          if (l==0) then         /* Implies that $a=1$.  Use $\ja{-1,0} = 1$ */
  2136.             ja0=((2*l+1)-(l+1-a)*g*jarray(l,a-1))/(l+a)
  2137.          else
  2138.             ja0=((2*l+1)*jarray(l-1,a-1)-
  2139.      $           (l+1-a)*g*jarray(l,a-1))/(l+a)
  2140.          end if
  2141.          do l=lmax-2,a-1,-1
  2142.             jarray(l+1,a)=ja0
  2143.             ja0=g*jarray(l+1,a)-
  2144.      $           z2*(l-a+2)*(l+a+2)*jarray(l+2,a)/((2*l+3)*(2*l+5))
  2145.          end do
  2146.          ja0=1/ja0
  2147.          do l=a,lmax
  2148.             jarray(l,a)=ja0*jarray(l,a)
  2149.          end do
  2150.       end do
  2151.  
  2152. @ Legendre functions of the first kind.  This returns $
  2153. |jarray(l,a)|=j\subb l1a(z)$ for $0\le l \le |lmax|$ and $0\le a \le
  2154. |amax|$.  In fact, we don't need this function; so it's commented out.
  2155.  
  2156. @<Functions...@>=
  2157. @#if 0
  2158.       subroutine legendrej(z,lmax,amax,jarray,lmax1)
  2159.  
  2160.       implicit_none
  2161.       integer l,a,lmax,amax,lmax1
  2162.       real z,jarray,scale
  2163.       dimension jarray(-lmax1-1:lmax1,0:amax)
  2164.       external legendrejs
  2165.  
  2166.       call legendrejs(z,lmax,amax,jarray,lmax1)
  2167.  
  2168.       scale=1
  2169.       do l=1,lmax
  2170.          scale=scale*z/(2*l+1)
  2171.          do a=0,amax
  2172.             jarray(l,a)=scale*jarray(l,a)
  2173.          end do
  2174.       end do
  2175.  
  2176.       scale=1
  2177.       do l=-1,-lmax-1,-1
  2178.          scale=scale/z*(2*l+3)
  2179.          do a=0,amax
  2180.             jarray(l,a)=scale*jarray(l,a)
  2181.          end do
  2182.       end do
  2183.  
  2184.       return
  2185.       end
  2186. @#endif
  2187.  
  2188. @ Calculate normalized Legendre functions needed in computation of
  2189. collision operator.  The single-index functions
  2190. $\jn l1a(u)$ are given in terms of $\ja{l,a}(u/c)$.
  2191. The multiple-index function are given in terms of the single-index
  2192. functions by by equations (A26):
  2193. $$\eqalign{
  2194. \jn l2{02}(u)&=\frac u2 \jn{l+1}11(u),\cr
  2195. \jn l2{11}(u)&=\frac u2 \jn{l+1}10(u),\cr
  2196. \jn l2{22}(u)&=\frac u2 \jn{l+1}11(u)+\frac{u^2}{2c^2} \jn{l+2}10(u),\cr
  2197. \jn l3{022}(u)&=\frac {u^2}8 \jn{l+2}10(u).\cr
  2198. }$$
  2199. The derivatives are given by equation (A21):
  2200. $$
  2201. \frac d{du}\jn lk*(u)=
  2202.   \frac1{\gamma}\jn{l-1}k*(u)-\frac{l+1}{u}\jn lk*(u).
  2203. $$
  2204. On output, this returns
  2205. $$\eqalign{
  2206. \hbox{|jarray(l,0)|} &= \jn l10(u), \cr
  2207. \hbox{|jarray(l,1)|} &= \jn l11(u), \cr
  2208. \hbox{|jarray(l,2)|} &= \jn l12(u), \cr
  2209. \hbox{|jarray(l,3)|} &= \jn l2{02}(u), \cr
  2210. \hbox{|jarray(l,4)|} &= \jn l2{11}(u), \cr
  2211. \hbox{|jarray(l,5)|} &= \jn l2{22}(u), \cr
  2212. \hbox{|jarray(l,6)|} &= \jn l3{022}(u), \cr
  2213. \hbox{|djarray(l,a)|} &=\frac d{du}\hbox{|jarray(l,a)|}, \cr
  2214. }$$
  2215. for $-|lmax|-1 \le l \le |lmax|$ and $0\le a \le |amax|$.  The dimensioning
  2216. of the arrays is controlled by |lmax1| which should be at least $|lmax|+2$,
  2217. in order to provide additional work space.
  2218.  
  2219. @ Here is |legendrejn|.
  2220.  
  2221. @<Functions...@>=
  2222.       subroutine legendrejn(u,c,lmax,jarray,djarray,lmax1)
  2223.  
  2224.       implicit_none
  2225.       integer j0,j1,j2,j02,j11,j22,j022
  2226.       parameter (j0=0, j1=1, j2=2, j02=3, j11=4, j22=5, j022=6)
  2227.  
  2228.       integer l,a,lmax,amax,lmax1
  2229.       real u,c,jarray,djarray,scale,g
  2230.       dimension jarray(-lmax1-1:lmax1,0:6),djarray(-lmax1-1:lmax1,0:6)
  2231.       external legendrejs
  2232.  
  2233.       amax=2
  2234.       call legendrejs(u/c,lmax+2,amax,jarray,lmax1)
  2235.  
  2236.       scale=1
  2237.       do l=1,lmax+2
  2238.          scale=scale*u/(2*l+1)
  2239.          do a=0,amax
  2240.             jarray(l,a)=scale*jarray(l,a)
  2241.          end do
  2242.       end do
  2243.  
  2244.       scale=1
  2245.       do l=-1,-lmax-2,-1
  2246.          scale=scale/u*(2*l+3)
  2247.          do a=0,amax
  2248.             jarray(l,a)=scale*jarray(l,a)
  2249.          end do
  2250.       end do
  2251.  
  2252.       do l=-lmax-2,lmax         /* Calculate multiple index solutions */
  2253.          jarray(l,j02) = u/2*jarray(l+1,1)
  2254.          jarray(l,j11) = u/2*jarray(l+1,0)
  2255.          jarray(l,j22) = u/2*jarray(l+1,1) + (u/c)^2/2*jarray(l+2,0)
  2256.          jarray(l,j022) = u^2/8*jarray(l+2,0)
  2257.       end do
  2258.  
  2259.       g = sqrt(1 + (u/c)**2)         /* Calculate derivatives */
  2260.       do a=0,6
  2261.          do l=-lmax-1,lmax
  2262.             djarray(l,a) = jarray(l-1,a)/g - (l+1)/u*jarray(l,a)
  2263.          end do
  2264.       end do
  2265.  
  2266.       return
  2267.       end
  2268.  
  2269. @* Index.
  2270.